【题解】P4390 [BalkanOI 2007] Mokia 摩基亚
【P4390】题解
一:【题面】
略
二:【解法】
把询问拆成四个前缀(t,x,y)
求多少修改(t,x,y)与它满足偏序关系
三:【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=8e5+10,M=2e6+10;
struct node{
int t,x,y;
int v;
int op;
LL ans,add;
}q[N];int K;
bool cmpt(node a,node b){
if(a.t!=b.t) return a.t<b.t;
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
bool cmpx(node a,node b){
if(a.x!=b.x) return a.x<b.x;
return a.y<b.y;
}
LL tree[M];
void update(int x,int d){
while(x<=K){
tree[x]+=d;
x+=x&-x;
}
}
int query(int x){
int res=0;
while(x){
res+=tree[x];
x-=x&-x;
}
return res;
}
void cdq(int l,int r){
if(l==r) return ;
int mid=l+r>>1;
cdq(l,mid);cdq(mid+1,r);
sort(q+l,q+1+mid,cmpx);sort(q+mid+1,q+1+r,cmpx);
int i=l,j=mid+1;
while(j<=r){
while(i<=mid&&q[i].x<=q[j].x){
if(q[i].op==1) update(q[i].y,q[i].v);
i++;
}
if(q[j].op==2) q[j].ans+=query(q[j].y);
j++;
}
for(int k=l;k<i;k++){
if(q[k].op==1) update(q[k].y,-q[k].v);
}
}
LL ans[N];
int ok[N];
int main(){
cin>>K>>K;
int t=0;
int idx=0;
while(1){
int op;cin>>op;
if(op==3) break;
t++;
if(op==1){
int x,y,a;cin>>x>>y>>a;
q[++idx]={t,x,y,a,1,0,0};
}
else{
ok[t]=1;
int xq1,yq1,xq2,yq2;cin>>xq1>>yq1>>xq2>>yq2;
xq1--;yq1--;
q[++idx]={t,xq2,yq2,0,2,0,1};//+
q[++idx]={t,xq1,yq1,0,2,0,1};//+
q[++idx]={t,xq1,yq2,0,2,0,-1};//-
q[++idx]={t,xq2,yq1,0,2,0,-1};//-
}
}
sort(q+1,q+1+idx,cmpt);
cdq(1,idx);
for(int i=1;i<=idx;i++){
if(q[i].op==1) continue;
int t=q[i].t;
ans[t]+=q[i].add*q[i].ans;
}
for(int i=1;i<=t;i++){
if(ok[i]) cout<<ans[i]<<"\n";
}
return 0;
}

浙公网安备 33010602011771号