http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=18802
题意:给n个矩形 会重叠,求出重叠k次以上的那一块矩形,然后输出里面的整点数
其实和求 k次覆盖的矩形的面积是一个道理
求k次覆盖矩形中,k不超过10,用sum[N][12],sum[N][i]存,该节点N管辖的区间范围内i次覆盖的有效长度,sum[N][k]存的是k次以上的有效长度(包含k次)
还有一个问题是,本题求的不是面积,是整点数,可知一点线段长度为x的话,整点应该是x+1个,为了方便处理,我们直接把每个矩形的右端点X2+1。
同理,如果是面积的话,矩形并的 最顶端那条线会被忽略,而这里是求整点,因此我们 把矩形的上端点y2也加1,然后就按照正常的做法即可。
#include <cstdio> #include <cmath> #include <cstring> #include <string> #include <algorithm> #include <iostream> #include <queue> #include <map> #include <set> #include <vector> using namespace std; const int N = 30005*2 ; struct node { int flag; long long lx,rx,y; node(){} node(int a,int b,int c,int d) { lx=a,rx=b,y=c,flag=d; } bool operator<(node b)const { return y<b.y; } }; node line[N]; long long X[N]; int add[4*N]; long long sum[N*4][12]; int k; void build(int i,int l,int r) { sum[i][0]=X[r+1]-X[l]; if (l==r) return ; int mid=(l+r)/2; build(i<<1,l,mid); build(i<<1|1,mid+1,r); } void pushup(int i,int l,int r) { memset(sum[i],0,sizeof sum[i]); if (l==r) sum[i][min(k,add[i])]=X[r+1]-X[l]; else { for (int j=0;j<=k;j++) sum[i][min(k,j+add[i])]+=sum[i<<1][j]+sum[i<<1|1][j]; } } void update(int i, int l, int r, int ql, int qr, int val) //更新区间为qlqr,当前区间为l,r,代表当前区间和的节点为i,更新值为val, { if(l > qr || ql > r) //更新区间不在当前区间内 return ; if(ql<=l&&qr>=r) //要更新的区间把当前区间完全包括,则把当前整个区间+val,然后返回上一层 { add[i] += val; pushup(i,l,r); return ; } int mid = (l + r) >> 1; update(i << 1, l, mid, ql, qr, val); update(i << 1 | 1, mid + 1, r, ql, qr, val); pushup(i,l,r); } int main() { int n ,a,b,i ; int cnt=1; int t;cin>>t; while(t--) { cin>>n>>k; memset(add,0,sizeof add); memset(sum,0,sizeof sum); int x1,x2,y1,y2; int num=0; for (int i=0;i<n;i++) { scanf("%d%d%d%d",&x1,&y1,&x2,&y2); y2++,x2++; line[++num]=node(x1,x2,y1,1); X[num]=x1; line[++num]=node(x1,x2,y2,-1); X[num]=x2; } sort(line+1,line+1+num); sort(X+1,X+1+num); int num_x=unique(X+1,X+1+num)-X-1; long long ans=0; build(1,0,num_x); for (int i=1;i<=num;i++) { if (i>1) ans+=sum[1][k]*(line[i].y-line[i-1].y); int l=lower_bound(X+1,X+1+num_x,line[i].lx)-X; int r=lower_bound(X+1,X+1+num_x,line[i].rx)-X-1; update(1,0,num_x,l,r,line[i].flag); } printf("Case %d: %lld\n",cnt++,ans); } }