【COGS】577 蝗灾 cdq分治

2024-09-05 14:58
文章标签 分治 cogs cdq 蝗灾

本文主要是介绍【COGS】577 蝗灾 cdq分治,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

传送门:【COGS】577 蝗灾


题目分析:cdq分治入门题= =。。。。用差分思想将矩阵分成四块来计算。。排序一维,另一维用树状数组解决。


代码如下:


#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std ;#define REP( i , a , b ) for ( int i = ( a ) ; i <  ( b ) ; ++ i )
#define FOR( i , a , b ) for ( int i = ( a ) ; i <= ( b ) ; ++ i )
#define REV( i , a , b ) for ( int i = ( a ) ; i >= ( b ) ; -- i )
#define CLR( a , x ) memset ( a , x , sizeof a )
#define CPY( a , x ) memcpy ( a , x , sizeof a )
#define mid ( ( l + r ) >> 1 )const int MAXN = 200005 ;
const int MAXM = 500005 ;struct Node {int x1 , y1 , x2 , y2 ;int v ;int op ;
} L[MAXN] , S[MAXN << 1] ;int n , m ;
int ans[MAXN] ;
int T[MAXM] ;void scanf ( int& x , char c = 0 ) {while ( ( c = getchar () ) < '0' || c > '9' ) ;x = c - '0' ;while ( ( c = getchar () ) >= '0' && c <= '9' ) x = x * 10 + c - '0' ;
}void modify ( int x , int v ) {while ( x <= m ) {T[x] += v ;x += x & -x ;}
}int sum ( int x , int ans = 0 ) {while ( x ) {ans += T[x] ;x -= x & -x ;}return ans ;
}int cmp ( const Node& a , const Node& b ) {return a.x1 != b.x1 ? a.x1 < b.x1 : a.op < b.op ;
}void cdq_solve ( int l , int r ) {if ( l == r ) return ;int m = mid , top = 0 ;cdq_solve ( l , m ) ;cdq_solve ( m + 1 , r ) ;FOR ( i , l , m ) if ( L[i].op == 1 ) S[top ++] = L[i] ;FOR ( i , m + 1 , r ) if ( L[i].op == 2 ) {S[top ++] = L[i] ;S[top - 1].x1 -- ;S[top ++] = L[i] ;S[top - 1].op = 3 ;S[top - 1].x1 = S[top - 1].x2 ;}sort ( S , S + top , cmp ) ;REP ( i , 0 , top ) {if ( S[i].op == 1 ) modify ( S[i].y1 , S[i].v ) ;else if ( S[i].op == 2 ) ans[S[i].v] -= sum ( S[i].y2 ) - sum ( S[i].y1 - 1 ) ;else ans[S[i].v] += sum ( S[i].y2 ) - sum ( S[i].y1 - 1 ) ;}REP ( i , l , m ) if ( L[i].op == 1 ) modify ( L[i].y1 , -L[i].v ) ;
}void solve () {int ans_cnt = 0 ;CLR ( T , 0 ) ;CLR ( ans , 0 ) ;scanf ( m ) ;scanf ( n ) ;FOR ( i , 1 , n ) {scanf ( L[i].op ) ;if ( L[i].op == 1 ) scanf ( L[i].x1 ) , scanf ( L[i].y1 ) , scanf ( L[i].v ) ;else {scanf ( L[i].x1 ) , scanf ( L[i].y1 ) , scanf ( L[i].x2 ) , scanf ( L[i].y2 ) ;L[i].v = ans_cnt ++ ;}}cdq_solve ( 1 , n ) ;REP ( i , 0 , ans_cnt ) printf ( "%d\n" , ans[i] ) ;
}int main () {freopen ( "locust.in" , "r" , stdin ) ;freopen ( "locust.out" , "w" , stdout ) ;solve () ;return 0 ;
}



这篇关于【COGS】577 蝗灾 cdq分治的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1139285

相关文章

Codeforces Round #240 (Div. 2) E分治算法探究1

Codeforces Round #240 (Div. 2) E  http://codeforces.com/contest/415/problem/E 2^n个数,每次操作将其分成2^q份,对于每一份内部的数进行翻转(逆序),每次操作完后输出操作后新序列的逆序对数。 图一:  划分子问题。 图二: 分而治之,=>  合并 。 图三: 回溯:

分治算法与凸包问题

1. 什么是凸包问题? 凸包问题是计算几何中的经典问题。给定二维平面上的点集,凸包是一个最小的凸多边形,它包含了点集中所有的点。你可以把凸包想象成一根松紧带将所有点紧紧包裹住的样子,凸包的边缘仅沿着最外面的点延伸。 2. 分治法简介 分治算法是解决复杂问题的强大策略,它的思想是将问题分解为多个子问题,分别解决这些子问题后再合并得到最终解。凸包问题可以通过分治算法高效地解决,时间复杂度可以达到

【COGS】256 [POI2001] 金矿 线段树

传送门:【COGS】256 [POI2001] 金矿 题目分析:将每个点作为一个矩阵的右下角添加这个矩阵的下边以及上边,这样本题转化成了区间加减以及求区间最大的问题。 代码如下: #include <cstdio>#include <vector>#include <cstring>#include <algorithm>using namespace std

【COGS】421 [SDOI2009] HH的项链 树状数组

传送门:【COGS】421 [SDOI2009] HH的项链 题目分析:将区间以右端点为关键字降序排序,然后从左到右依次遍历每个数并插入到树状数组中,如果遍历到一个数的时候在他的前面已经有一个相同的数时,将之前位置上的数从树状数组中删除。然后我们每处理完一个位置上的数后,看这个位置上是否有右端点,如果有则做一次求和,这个右端点属于的区间【L,R】的值即sum(R)-sum(L-1)。

【ACdream】1157 Segments cdq分治

传送门:【ACdream】1157 Segments 题目分析:第一题cdq(陈丹琦)分治!cdq_____Orz! 听说cdq分治可以写,就去学了cdq分治了。。 在我们平常使用的分治中,每一个子问题只解决它本身(可以说是封闭的)。 而在cdq分治中,对于划分出来的两个子问题,前一个子问题用来解决后一个子问题而不是它本身。 具体算法流程如下: 1.将整个操作序列分为两个长

【HDU】4871 Shortest-path tree 最短路+点分治

传送门:【HDU】4871 Shortest-path tree 题目分析: 学了点分治后来看这道题,简直就是水题。。。 但是我竟然花了将近一个晚上才写出来。。。就因为一个地方写漏了T U T。。 首先根据题意求一棵树,最短路一下,然后最小字典序就按照编号顺序遍历邻接表给节点标记。 剩下的就是树分治的事了。 在以重心X为根的子树中,按照X的子节点v的子树中最长路径包含节点数升序遍

【HDU】4812 D Tree 点分治

传送门:【HDU】4812 D Tree 题目分析:点分治搞之。乘积等于K的路径。 首先我们定义一个path[ i ]用以记录从根结点x在子树x内的第 i 条路径的值(乘积)。然后每次我们搞完当前重心rt的一棵子树以后,我们用判断K*逆元[ path[ i ] * val[ rt ] %MOD ] % MOD 是否存在来确定乘积为K的路径是否存在,然后再用这个path[ i ]去更

【SPOJ】1825 Free tour II 点分治

传送门:【SPOJ】1825 Free tour II 题目分析:敲了两遍。。。 本题是论文题,具体见漆子超论文《分治算法在树的路径问题中的应用》。 在以root为根的第 i 棵子树上,我们用G[ i ,j ]表示root的第 i 棵子树的路径上严格有 j 个黑点的路径的最长长度。用F[ i ,j ]表示在root为根的第 i 棵子树的路径上不超过 j 个黑点的路径的最长长度。因

【HDU】4670 Cube number on a tree 点分治

传送门:【HDU】4670 Cube number on a tree 题目分析:首先因为至多30个素数,3^30在long long以内,如果一条路径上的数的乘积是个立方数,则这条路径上每个素数因子的个数都应该是3的倍数,于是我们用三进制表示含有素数的状态,当且仅当状态为0(即所有素数的个数都是3的倍数)时这条路径上数的乘积为完全立方数。考虑树分治,每层分治,求出当前重心的一个儿子的一个