tsinsen A1333

可以用二维树状数组套值域线段树来做,复杂度:O( (n*n+q) * logn logn log10^9 )

但作为作为整体二分的例题,还是用整体二分来写了一下。对整体二分有一点感觉了。

整体二分,顾名思义,二分答案,只不过不是对单独一个询问,而是对所有询问,具体过程可以想象成对询问的不断分类(根据其答案区间不断往下分)。比如最开始所有询问的答案区间是[amin,amax],我们现在分出两个区间[amin,amid],和[amid+1,amax],然后将当前区间[amin,amax]的所有询问根据某些信息,分配到两个区间,使得其答案的可能的区间范围就是它所属的区间,当区间长度为1时,该区间包含的询问的答案就是该区间的那个数。

形象一点,可以把二分比作赶鸭子(询问)回窝(答案),单独对一个询问二分是只赶一只鸭子,向左区间或右区间赶,直到回窝,而整体二分就是赶一群鸭子,前者只需单刀直入,找到答案,而后者还需要回朔。

整体二分的优势是可以在分配询问时共享一些东西,从而避免掉每次单独算的低效,从而优化复杂度。

  1 #include <cstdio>
  2 #include <vector>
  3 #include <algorithm>
  4 #define oo 0x3f3f3f3f
  5 #define N 510
  6 #define M 60010
  7 using namespace std;
  8
  9 struct Pair {
 10     int v;
 11     int x, y;
 12     Pair(){}
 13     Pair( int v, int x, int y ):v(v),x(x),y(y){}
 14     bool operator<( const Pair &o ) const {
 15         return v<o.v;
 16     }
 17 };
 18 bool operator<( const Pair &a, int b ) {
 19     return a.v<b;
 20 }
 21 bool operator<( int a, const Pair &b ) {
 22     return a<b.v;
 23 }
 24 struct Query {
 25     int id;
 26     int xmin, xmax;
 27     int ymin, ymax;
 28     int k;
 29     Query( int id, int x0, int x1, int y0, int y1, int k ):
 30         id(id),xmin(x0),xmax(x1),ymin(y0),ymax(y1),k(k){}
 31 };
 32
 33 int n, m;
 34 int ww[N][N], vmin, vmax;
 35 int bit[N][N];
 36 int ans[M];
 37 Pair prs[N*N]; int ptot;
 38 vector<Query> vq;
 39 int q[N*N];
 40
 41 void modify( int x, int y, int v ) {
 42     for( register int i=x; i<=n; i+=i&-i )
 43         for( register int j=y; j<=n; j+=j&-j )
 44             bit[i][j] += v;
 45 }
 46 int query( int x, int y ) {
 47     int rt = 0;
 48     for( register int i=x; i; i-=i&-i )
 49         for( register int j=y; j; j-=j&-j )
 50             rt += bit[i][j];
 51     return rt;
 52 }
 53 int query( int xmin, int xmax, int ymin, int ymax ) {
 54     return query(xmax,ymax)-query(xmin-1,ymax)-query(xmax,ymin-1)+query(xmin-1,ymin-1);
 55 }
 56 void binary( int lf, int rg, vector<Query> vq ) {
 57     if( vq.empty() ) return;
 58     if( lf==rg ) {
 59         for( int t=0; t<vq.size(); t++ )
 60             ans[vq[t].id] = lf;
 61         return;
 62     }
 63     int mid=lf+((rg-lf)>>1);
 64     int lpos = lower_bound( prs+1, prs+1+ptot, lf ) - prs;
 65     int rpos = upper_bound( prs+1, prs+1+ptot, mid ) - prs - 1;
 66     for( int i=lpos; i<=rpos; i++ )
 67         modify( prs[i].x, prs[i].y, +1 );
 68     vector<Query> ql, qr;
 69     for( int t=0; t<vq.size(); t++ ) {
 70         int c = query( vq[t].xmin, vq[t].xmax, vq[t].ymin, vq[t].ymax );
 71         if( vq[t].k<=c )
 72             ql.push_back( vq[t] );
 73         else {
 74             qr.push_back( vq[t] );
 75             qr.back().k -= c;
 76         }
 77     }
 78     for( int i=lpos; i<=rpos; i++ )
 79         modify( prs[i].x, prs[i].y, -1 );
 80     binary( lf, mid, ql );
 81     binary( mid+1, rg, qr );
 82 }
 83 int main() {
 84     scanf( "%d%d", &n, &m );
 85     vmin=oo, vmax=-oo;
 86     for( int i=1; i<=n; i++ )
 87         for( int j=1; j<=n; j++ ) {
 88             scanf( "%d", &ww[i][j] );
 89             vmin = min( vmin, ww[i][j] );
 90             vmax = max( vmax, ww[i][j] );
 91             prs[++ptot] = Pair( ww[i][j], i, j );
 92         }
 93     sort( prs+1, prs+1+ptot );
 94     for( int i=1,x0,x1,y0,y1,k; i<=m; i++ ) {
 95         scanf( "%d%d%d%d%d", &x0, &y0, &x1, &y1, &k );
 96         vq.push_back( Query( i, x0, x1, y0, y1, k ) );
 97     }
 98     binary( vmin, vmax, vq );
 99     for( int i=1; i<=m; i++ )
100         printf( "%d\n", ans[i] );
101 }

时间: 2024-09-11 11:19:59

tsinsen A1333的相关文章

Tsinsen A1333: 矩阵乘法(整体二分)

http://www.tsinsen.com/A1333 题意:-- 思路:和之前的第k小几乎一样,只不过把一维BIT换成二维BIT而已.注意二维BIT写法QAQ 1 #include <cstdio> 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <string> 6 #include <cmath> 7 #include &

tsinsen A1333. 矩阵乘法

题目链接:传送门 题目思路:整体二分(二分的是答案,附带的是操作) 把矩阵中的元素对应成插入操作,然后就有插入和询问操作. 然后根据插入操作对于答案的影响,询问操作所匹配的符合答案个数,将操作分为两段,继续递归... #include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <algorithm> #include <cstring&

Tsinsen A1493 城市规划(DP + CDQ分治 + NTT)

题目 Source http://www.tsinsen.com/A1493 Description 刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了. 刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多

Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB 总提交次数:196   AC次数:65   平均分:58.62 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2013中国国家集训队第二次作业 问题描述 给定一棵N个节点的树,每个点有一个权值,有M个询问(a,b,c)若a 为1,回答b到c路径上的最小权值,若a为2,回答b到c路径上的最大权值,若a为3,回答b到c路径上的所有权值的

Tsinsen A1517. 动态树 树链剖分,线段树,子树操作

题目 : http://www.tsinsen.com/A1517 A1517. 动态树 时间限制:3.0s   内存限制:1.0GB 总提交次数:227   AC次数:67   平均分:49.52 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 中国国家队清华集训 2013-2014 第四天 问题描述 小明在楼下种了一棵动态树, 该树每天会在某些节点上长出一些果子. 这棵树的根节点为1, 它有n个节点, n-1条边. 别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求

Tsinsen A1516. fx 数位dp

题目: http://www.tsinsen.com/A1516 A1516. fx 时间限制:2.0s   内存限制:256.0MB 总提交次数:164   AC次数:72   平均分:51.28 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 中国国家队清华集训 2013-2014 第四天 问题描述 对于一个n位的十进制数x(AnAn-1……A1),我们定义它的权重为: F(x)=An*2n-1+An-1*2n-2+……+A1*20 现在,给你两个十进制数A和B,请计算

tsinsen A1486. 树(王康宁) 边分治+字典树

不知为何,这个代码只能得95分 放一下傻逼代码... #include<iostream> #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int n,K; int nn2=1,nn=1,nod; #define N 1000000 #define ed(x) (x>>1) #define ab(x) ((x)>0?(x):-(x)) i

Tsinsen A1504. Book(王迪) 数论,贪心

题目:http://www.tsinsen.com/A1504 A1504. Book(王迪) 时间限制:1.0s   内存限制:256.0MB   Special Judge 总提交次数:359   AC次数:97   平均分:43.76 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2013中国国家集训队第二次作业 问题描述 Wayne喜欢看书,更喜欢买书. 某天Wayne在当当网上买书,买了很多很多书.Wayne有一个奇怪的癖好,就是第一本书的价格必须恰为X,而之后

【Tsinsen】【A1365】森林旅店

KD-Tree 啊哈~检验了一下自己KD-Tree的学习情况,还算可以,模板至少是记下来了. 支持插入(所以要带重建),查询最近的P个点的距离. 然而题目并没有说是按怎样的顺序输出这P个点?...(事实上是从近到远) 没啥好讲的……就是KD-Tree的裸操作…… 1 //Tsinsen A1365 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #incl