bzoj2683: 简单题&bzoj1176: [Balkan2007]Mokia

题目
题解
cdq分治+树状数组,这里贴的是2683的代码,1176还要改一下

#include<bits/stdc++.h>
using namespace std;
const int M=800002,N=500002;
struct node{
    int fl,x,y,v,pos,id;
}a[M],b[M];
int ans[N],s,cnt,tot,i,x,y,xx,yy,n,tr[N],opt,v;
inline char gc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
#define gc getchar
inline int read(){
    int x=0,fl=1;char ch=gc();
    for (;ch<48||ch>57;ch=gc())if(ch=='-')fl=-1;
    for (;48<=ch&&ch<=57;ch=gc())x=(x<<3)+(x<<1)+(ch^48);
    return x*fl;
}
inline void wri(int a){if(a<0)a=-a,putchar('-');if(a>=10)wri(a/10);putchar(a%10|48);}
inline void wln(int a){wri(a);puts("");}
void add(int x,int y){
    for (;x<=n;x+=x&-x) tr[x]+=y;
}
int query(int x){
    int s=0;
    for (;x;x^=x&-x) s+=tr[x];
    return s;
}
void solve(int l,int r){
    if (l>=r) return;
    int mid=l+r>>1,k1=l,k2=mid+1;
    for (int i=l;i<=r;i++){
        if (!a[i].fl && a[i].pos<=mid) add(a[i].y,a[i].v);
        if (a[i].fl && a[i].pos>mid) ans[a[i].id]+=query(a[i].y)*a[i].v;
    }
    for (int i=l;i<=r;i++)
        if (!a[i].fl && a[i].pos<=mid) add(a[i].y,-a[i].v);
    for (int i=l;i<=r;i++)
        if (a[i].pos<=mid) b[k1++]=a[i];
        else b[k2++]=a[i];
    for (int i=l;i<=r;i++) a[i]=b[i];
    solve(l,mid);solve(mid+1,r);
}
bool cmp(node a,node b){
    return a.x<b.x || a.x==b.x && a.pos<b.pos;
}
int main(){
    n=read();
    while (1){
        opt=read();if (opt==3) break;
        x=read();y=read();
        if (opt==1){
            v=read();
            a[++cnt]=(node){0,x,y,v,cnt,0};
        }else{
            xx=read();yy=read();tot++;
            a[++cnt]=(node){1,xx,yy,1,cnt,tot};
            a[++cnt]=(node){1,xx,y-1,-1,cnt,tot};
            a[++cnt]=(node){1,x-1,yy,-1,cnt,tot};
            a[++cnt]=(node){1,x-1,y-1,1,cnt,tot};
        }
    }
    sort(a+1,a+cnt+1,cmp);
    solve(1,cnt);
    for (i=1;i<=tot;i++) wln(ans[i]); 
}

猜你喜欢

转载自blog.csdn.net/xumingyang0/article/details/80753636