Luogu P3374 【模板】树状数组 1

看题面戳我

一道常规的二维偏序,用前缀和的思想把求[l,r]分成[1,r]-[1,l-1]

带修改条件的,是从二维进阶到三维的必备题

#include<cstdio>
using namespace std;

const int N=2e6+5;
int n,m,c,cnt,ans[N];
struct A{int id,k,x,y; }q[N],t[N];

void work(int l,int r)
{
    if(l==r) return; 
    int mid=l+r>>1;  
    work(l,mid),work(mid+1,r);
    int i=l,j=mid+1,k=l,y=0;
    while(i<=mid&&j<=r)
    {
    	if(q[i].x<=q[j].x) 
		{
			t[k++]=q[i];
			if(q[i].k==1) y+=q[i].y;
			i++;
		} else
		{
			t[k++]=q[j];
			if(q[j].k==2) ans[q[j].id]-=y;
				else if(q[j].k==3) ans[q[j].id]+=y;
			j++;
		}
	}
	while(i<=mid) t[k++]=q[i++];
	while(j<=r) 
	{
		t[k++]=q[j];
		if(q[j].k==2) ans[q[j].id]-=y;
			else if(q[j].k==3) ans[q[j].id]+=y;
		j++;
	}
	for(int i=l;i<=r;i++) q[i]=t[i];
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        int	x; scanf("%d",&x);
        q[++c]=(A){0,1,i,x};
    }
    for(int i=1;i<=m;i++)
    {
        int k,x,y; scanf("%d%d%d",&k,&x,&y);
        if(k==1) q[++c]=(A){0,k,x,y};
            else q[++c]=(A){++cnt,2,x-1,0},q[++c]=(A){cnt,3,y,0};
    }
    work(1,c);
    for(int i=1;i<=cnt;i++) printf("%d\n",ans[i]);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/YYHS_WSF/article/details/84727521