C60 可持久化线段树+离散化+二分 P3755 [CQOI2017] 老C的任务
视频链接:246 可持久化线段树+离散化+二分 P3755 [CQOI2017] 老C的任务_哔哩哔哩_bilibili
#include <iostream> #include <cstring> #include <algorithm> using namespace std; void read(int &x){ //快读 x=0;int f=1;char c=getchar(); while(!isdigit(c)){if(c=='-')f=-1;c=getchar();} while(isdigit(c)){x=x*10+c-'0',c=getchar();} x*=f; } typedef long long ll; const int N=100005; #define mid ((l+r)>>1) struct node{ int x,y,p; //p:权值 node(int x1=0,int y1=0):x(x1),y(y1){} bool operator<(const node &b)const{return x<b.x;} }a[N]; int n,m,y[N]; int root[N],tot; //根节点,开点个数 int ls[N*20],rs[N*20]; ll sum[N*20]; //sum:区间权值的前缀和 void change(int &u,int v,int l,int r,int y,int p){ //点修 u=++tot; //动态开点 ls[u]=ls[v],rs[u]=rs[v],sum[u]=sum[v]+p; if(l==r) return; if(y<=mid) change(ls[u],ls[v],l,mid,y,p); else change(rs[u],rs[v],mid+1,r,y,p); } ll query(int u,int l,int r,int x,int y){ //区查 if(x>r||y<l) return 0; if(x<=l&&r<=y) return sum[u]; return query(ls[u],l,mid,x,y) +query(rs[u],mid+1,r,x,y); } int main(){ read(n);read(m); int x1,y1,x2,y2; for(int i=1;i<=n;i++) read(a[i].x),read(a[i].y),read(a[i].p); for(int i=1;i<=n;i++) y[i]=a[i].y; sort(y+1,y+1+n); int yn=unique(y+1,y+1+n)-y-1; for(int i=1;i<=n;i++) //y值离散化 a[i].y=lower_bound(y+1,y+1+yn,a[i].y)-y; sort(a+1,a+1+n); //按x排序 for(int i=1;i<=n;i++) //持久树:版本对应x的下标 change(root[i],root[i-1],1,yn,a[i].y,a[i].p); while(m--){ read(x1),read(y1),read(x2),read(y2); x1=lower_bound(a+1,a+1+n,node(x1,0))-a; x2=upper_bound(a+1,a+1+n,node(x2,0))-a-1; y1=lower_bound(y+1,y+1+yn,y1)-y; y2=upper_bound(y+1,y+1+yn,y2)-y-1; printf("%lld\n",query(root[x2],1,yn,y1,y2) -query(root[x1-1],1,yn,y1,y2)); } }