题解 P4390 【[BOI2007]Mokia 摩基亚】
这道题我爱了!
思路
看到这题目我直接想到了三值偏序,然后我就开始了不归之路
1.把操作按时间排序,就能离线操作了
2.首先读入的时候各个操作已经默认是按时间排序的了,所以不用考虑时间这一维
接着,操作分两种:
(1).添加住户(相当于是把这个点的权值加上一个a)
(2).查询住户(查询的这个范围是个矩形)
所以自然就可以用归并排序+树状数组来解决了
其中最妙的一步在于将操作2中的给出的两个点进行扩展,扩展成4个点来进行操作,然后在归并排序的时候按照坐标x来排序,根据树状数组的性质来进行操作:
结合代码来讲一下
for (;tql!=3;){
cin>>tql;
if(tql == 1)R++,T[R].tt=R,cin>>T[R].x>>T[R].y>>T[R].z;
if(tql == 2){
R++;
int m=R;
book[m]=1;
R=R,T[R].t=1,cin>>T[R].x>>T[R].y,T[R].tt=m;
T[R].x--,T[R].y--;
R++,T[R].t=4,cin>>T[R].x>>T[R].y,T[R].tt=m;
R++,T[R].t=2,T[R].x=T[R-2].x,T[R].y=T[R-1].y,T[R].tt=m;
R++,T[R].t=3,T[R].x=T[R-2].x,T[R].y=T[R-3].y,T[R].tt=m;
}
}
(见tql==2的情况)
(给拓展的四个点进行标记然后在后面计算答案)
if(T[t2].t == 1)tong[T[t2].tt]+=get(T[t2].y);
if(T[t2].t == 2)tong[T[t2].tt]-=get(T[t2].y);
if(T[t2].t == 3)tong[T[t2].tt]-=get(T[t2].y);if(T[
t2].t == 4)tong[T[t2].tt]+=get(T[t2].y);
此处请自行脑补一个树状数组
借用前面题解的图片来理解
CODE
#include <bits/stdc++.h>
using namespace std;
int c[2005001];
int tong[200001];
int w,tql,R=0;
struct node{int x,y,z,t,tt;}T[200001],p[200001];
int book[200005];
int lowbit(int x){return x&(-x);}
int add(int x,int k){
while(x <= w)c[x]+=k,x+=lowbit(x);
return 0;
}
int get(int x){
int total=0;
while(x > 0)
total+=c[x],x-=lowbit(x);
return total;
}
int CDQ(int l , int r ){
if(l == r)return 0;
int mid=(l+r)>>1;
CDQ(l,mid);CDQ(mid+1,r);
int t1=l,t2=mid+1;
for (int i = l ; i <= r ; i ++){
if(T[t1].x <= T[t2].x && t1 <=mid || t2 > r){
if(T[t1].t == 0)add(T[t1].y,T[t1].z);
p[i]=T[t1],t1++;
}
else {
if(T[t2].t == 1)tong[T[t2].tt]+=get(T[t2].y);
if(T[t2].t == 2)tong[T[t2].tt]-=get(T[t2].y);
if(T[t2].t == 3)tong[T[t2].tt]-=get(T[t2].y);
if(T[t2].t == 4)tong[T[t2].tt]+=get(T[t2].y);
p[i]=T[t2],t2++;
}
}
for (int i = l ; i <= mid ; i ++)
if(T[i].t == 0)add(T[i].y,-T[i].z);
for (int i = l ; i <= r ; i ++)
T[i]=p[i];
return 0;
}
int main(){
cin>>tql>>w;
R=0;
for (;tql!=3;){
cin>>tql;
if(tql == 1)R++,T[R].tt=R,cin>>T[R].x>>T[R].y>>T[R].z;
if(tql == 2){
R++;
int m=R;
book[m]=1;
R=R,T[R].t=1,cin>>T[R].x>>T[R].y,T[R].tt=m;
T[R].x--,T[R].y--;
R++,T[R].t=4,cin>>T[R].x>>T[R].y,T[R].tt=m;
R++,T[R].t=2,T[R].x=T[R-2].x,T[R].y=T[R-1].y,T[R].tt=m;
R++,T[R].t=3,T[R].x=T[R-2].x,T[R].y=T[R-3].y,T[R].tt=m;
}
if(tql == 3)break;
}
CDQ(1,R);
for (int i = 1 ; i <= R ; i ++)
if(book[i] != 0)cout<<tong[i]<<endl;
return 0;
}
By MYCui