COGS 577 蝗灾 线段树+CDQ分治

第一次写cdq分治 感谢hhd&lty 这20亿对CP的指导(逃)

其实 就是 递归看左半部分对右半部分的贡献

(树状数组写挂了……临时改的线段树【大写的尴尬】)

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 666666
int w,n,tree[N*16];
struct Oper{int op,id,x1,y1,x2,y2,z,ans;}a[N],b[N];
bool cmp(Oper a,Oper b){return a.x1<b.x1||(a.x1==b.x1&&a.op<b.op);}
void add(int l,int r,int pos,int num,int wei){
    if(l==r){tree[pos]+=wei;return;}
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(mid<num)add(mid+1,r,rson,num,wei);
    else add(l,mid,lson,num,wei);
    tree[pos]=tree[lson]+tree[rson];
}
int query(int l,int r,int pos,int num){
    if(num>=r)return tree[pos];
    int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
    if(mid>=num)return query(l,mid,lson,num);
    else return query(l,mid,lson,num)+query(mid+1,r,rson,num);
}
void cdq(int l,int r){
    if(l==r)return;
    int mid=(l+r)>>1,cnt=0;
    cdq(l,mid),cdq(mid+1,r);
    for(int i=l;i<=mid;i++)if(a[i].op==1)b[cnt++]=a[i];
    for(int i=mid+1;i<=r;i++)if(a[i].op==2){
        b[cnt]=a[i],b[cnt++].x1--;
        b[cnt]=a[i],b[cnt].x1=a[i].x2;b[cnt++].op=3;
    }
    sort(b,b+cnt,cmp);
    for(int i=0;i<cnt;i++)
        if(b[i].op==1)add(0,w,1,b[i].y1,b[i].z);
        else a[b[i].id].ans+=((b[i].op == 2)?-1:1)*(query(0,w,1,b[i].y2)-query(0,w,1,b[i].y1-1));
    for(int i=0;i<cnt;i++)if(b[i].op==1)add(0,w,1,b[i].y1,-b[i].z);
}
int main(){
    freopen("locust.in","r",stdin);
    freopen("locust.out","w",stdout);
    scanf("%d%d",&w,&n);
    for(int i=1;i<=n;a[i].id=i,i++){
        scanf("%d%d%d",&a[i].op,&a[i].x1,&a[i].y1);
        if(a[i].op==1)scanf("%d",&a[i].z);
        else scanf("%d%d",&a[i].x2,&a[i].y2);
    }cdq(1,n);
    for(int i=1;i<=n;i++)if(a[i].op==2)printf("%d
",a[i].ans);
}
原文地址:https://www.cnblogs.com/SiriusRen/p/6532150.html