【题解】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;
}
posted @ 2025-12-26 14:57  Ming3398  阅读(1)  评论(0)    收藏  举报