【BZOJ】4170: 极光-cdq分治

传送门:bzoj4170


题解

当我们知道可以把价值看成y坐标并把(x,y)的菱形转化为(x-y,x+y)的矩形来cdq时,这道题就成模板了。
真妙啊


代码

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define mid ((l+r)>>1)
typedef long long ll;
using namespace std;
const int N=5e6+10;
const int M=6e4+10;
int cnt,n,Q,tot,MX,a[M];
ll ans[500010],tre[500010];//2.space 80000->500010
char s[15];
struct P{int v,x,y,id;}q[N],tp[N];
inline int max(int x,int y){return x>y?x:y;}

inline int rd()
{
    char ch=getchar();int x=0,f=1;
    while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
    while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*f;
}
inline void ad(int x,int v)
{for(;x<=MX && x!=0;x+=(x&(-x))) tre[x]+=v;}//x!=0
inline ll get(int x)
{ll ret=0;for(;x>0;x-=(x&(-x))) ret+=tre[x];return ret;}

void cdq(int l,int r)
{
    if(l==r) return;
    int i,j,L=l,R=mid+1;
    cdq(l,mid);cdq(mid+1,r);
    for(i=R,j=l;i<=r;i++){
        for(;j<=mid && q[j].x<=q[i].x;j++) if(!q[j].v) ad(q[j].y,1);
        if(q[i].v) ans[q[i].id]+=q[i].v*get(q[i].y);
    }
    for(i=l;i<=mid && q[i].x<=q[r].x;i++) if(!q[i].v) ad(q[i].y,-1);
    for(i=l;i<=r;i++){
        if((q[L].x<=q[R].x || R>r) && L<=mid) tp[i]=q[L++];
        else tp[i]=q[R++];
    } 
    for(i=l;i<=r;i++) q[i]=tp[i];
}

int main(){
    int i,X,K;
    n=rd();Q=rd();
    for(i=1;i<=n;i++){a[i]=rd();q[++cnt].x=i-a[i];q[cnt].y=i+a[i];MX=max(MX,max(q[cnt].x,q[cnt].y));}
    for(i=1;i<=Q;i++){
        scanf("%s",s);X=rd();K=rd();
        if(s[0]=='M'){q[++cnt].x=X-K;q[cnt].y=X+K;a[X]=K;MX=max(MX,max(q[cnt].x,q[cnt].y));}
        else{
            q[++cnt].x=X-a[X]+K;q[cnt].y=X+a[X]+K;q[cnt].v=1;q[cnt].id=++tot;
            MX=max(MX,max(q[cnt].x,q[cnt].y));
            q[++cnt].x=X-a[X]-K-1;q[cnt].y=X+a[X]+K;q[cnt].v=-1;q[cnt].id=tot;
            if(X+a[X]>K+1){
              q[++cnt].x=X-a[X]+K;q[cnt].y=X+a[X]-K-1;q[cnt].v=-1;q[cnt].id=tot;
              q[++cnt].x=X-a[X]-K-1;q[cnt].y=X+a[X]-K-1;q[cnt].v=1;q[cnt].id=tot;   
            }
        }
    }MX++;
    cdq(1,cnt);
    for(i=1;i<=tot;i++) printf("%lld\n",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/80399191