C60 可持久化线段树+离散化+二分 P3755 [CQOI2017] 老C的任务

视频链接:246 可持久化线段树+离散化+二分 P3755 [CQOI2017] 老C的任务_哔哩哔哩_bilibili

 

 

Luogu P3755 [CQOI2017] 老C的任务

#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));
  }
}

 

posted @ 2023-11-07 12:40  董晓  阅读(131)  评论(0编辑  收藏  举报