HDU 4578 Transformation

Time limit 8000 ms
Memory limit 65536 kB
OS Windows
Source 2013ACM-ICPC杭州赛区全国邀请赛

感想

线段树加法乘法大合集,有了这些操作,其他的区间平均值、区间方差什么的都不是事儿了。和这题相比,[AHOI2009]维护序列就太简单了,只有乘法加法区间和……

顺便,一开始不说p的大小,直到输入那里才说是想吓死人啊。

解题思路

和维护序列那题一样,依然从标记之间的关系来看,推一推公式,看一个操作对该区间的其他标记、总和、平方和、立方和的影响。

时间不早了,扔两个链接,去睡了敷衍

垃圾CSDN,开始封禁博客园链接了,急了吧,让你之前设计反人类,让你广告恶心人,活该用户变少

源代码

我这代码仿佛在打表

#include<stdio.h>
#include<string.h>
#include<algorithm>

const long long mod=10007;
int T;
int n,m;
struct Node{
	int l,r;
	long long lazyadd,lazymul,lazyset;
	//0,1,-1.设置set标记时,马上清空add、mul。下放时,如果三个都有,说明是在set之后放的
	long long sum[4];
}t[400010];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}

void build(int x,int l,int r)
{
	memset(&t[x],0,sizeof(t[x]));
	t[x].l=l;
	t[x].r=r;
	t[x].lazymul=1;
	t[x].lazyset=-1;
	if(l==r) return;
	int mid=l+r>>1;
	build(ls(x),l,mid);
	build(rs(x),mid+1,r);
}

inline void pushdown(int x)
{
	if(~t[x].lazyset)
	{
		long long b=t[x].lazyset%mod;
		t[x].lazyset=-1;
        int len=t[ls(x)].r-t[ls(x)].l+1;
		t[ls(x)].sum[1]=len*b%mod;
		t[ls(x)].sum[2]=len*b%mod*b%mod;
		t[ls(x)].sum[3]=len*b%mod*b*b%mod;
		len=(t[rs(x)].r-t[rs(x)].l+1);
		t[rs(x)].sum[1]=len*b%mod;
		t[rs(x)].sum[2]=len*b%mod*b%mod;
		t[rs(x)].sum[3]=len*b%mod*b*b%mod;
		t[ls(x)].lazyset=t[rs(x)].lazyset=b;
		t[ls(x)].lazyadd=t[rs(x)].lazyadd=0;
		t[ls(x)].lazymul=t[rs(x)].lazymul=1;
	}
	if(t[x].lazymul!=1)
	{
		long long b = t[x].lazymul%mod;
		t[x].lazymul = 1;

		t[ls(x)].lazyadd*=b;t[ls(x)].lazyadd%=mod;
		t[ls(x)].lazymul*=b;t[ls(x)].lazymul%=mod;
		t[ls(x)].sum[1]*=b;
		t[ls(x)].sum[2]*=b*b%mod;
		t[ls(x)].sum[3]*=b*b%mod*b;
		t[ls(x)].sum[1]%=mod;
		t[ls(x)].sum[2]%=mod;
		t[ls(x)].sum[3]%=mod;

		t[rs(x)].lazyadd*=b;t[rs(x)].lazyadd%=mod;
		t[rs(x)].lazymul*=b;t[rs(x)].lazymul%=mod;
		t[rs(x)].sum[1]*=b;
		t[rs(x)].sum[2]*=b*b%mod;
		t[rs(x)].sum[3]*=b*b%mod*b;
		t[rs(x)].sum[1]%=mod;
		t[rs(x)].sum[2]%=mod;
		t[rs(x)].sum[3]%=mod;
	}
	if(t[x].lazyadd)
	{
		long long b=t[x].lazyadd;//////顺序321
		t[x].lazyadd=0;
		int len=t[ls(x)].r-t[ls(x)].l+1;
		t[ls(x)].sum[3]+=len*b%mod*b*b%mod+t[ls(x)].sum[1]*b%mod*b*3%mod+t[ls(x)].sum[2]*b*3%mod;
		t[ls(x)].sum[2]+=len*b%mod*b%mod+t[ls(x)].sum[1]*b*2%mod;
		t[ls(x)].sum[1]+=len*b%mod;
		t[ls(x)].sum[1]%=mod;
		t[ls(x)].sum[2]%=mod;
		t[ls(x)].sum[3]%=mod;
		t[ls(x)].lazyadd+=b;t[ls(x)].lazyadd%=mod;
		len=t[rs(x)].r-t[rs(x)].l+1;
		t[rs(x)].sum[3]+=len*b%mod*b*b%mod+t[rs(x)].sum[1]*b%mod*b*3%mod+t[rs(x)].sum[2]*b*3%mod;
		t[rs(x)].sum[2]+=len*b%mod*b%mod+t[rs(x)].sum[1]*b*2%mod;
		t[rs(x)].sum[1]+=len*b%mod;
		t[rs(x)].sum[1]%=mod;
		t[rs(x)].sum[2]%=mod;
		t[rs(x)].sum[3]%=mod;
		t[rs(x)].lazyadd+=b;t[rs(x)].lazyadd%=mod;
	}
}

inline void pushup(int x)
{
	t[x].sum[1]=(t[ls(x)].sum[1]+t[rs(x)].sum[1])%mod;
	t[x].sum[2]=(t[ls(x)].sum[2]+t[rs(x)].sum[2])%mod;
	t[x].sum[3]=(t[ls(x)].sum[3]+t[rs(x)].sum[3])%mod;
}

void add(int x,int l,int r,long long k)
{
	if(l<=t[x].l&&t[x].r<=r)
	{
		t[x].lazyadd+=k;
		t[x].lazyadd%=mod;
		int len=t[x].r-t[x].l+1;
		t[x].sum[3]+=3*k*t[x].sum[2]%mod+3*k*k%mod*t[x].sum[1]%mod+len*k%mod*k*k%mod;
		t[x].sum[2]+=2*k*t[x].sum[1]%mod+len*k%mod*k%mod;
		t[x].sum[1]+=len*k%mod;
		t[x].sum[1]%=mod;
		t[x].sum[2]%=mod;
		t[x].sum[3]%=mod;
		return;
	}
	int mid=t[x].l+t[x].r>>1;
	pushdown(x);
	if(l<=mid) add(ls(x),l,r,k);
	if(r>mid) add(rs(x),l,r,k);
	pushup(x);
}

void mult(int x,int l,int r,long long k)
{
	if(l<=t[x].l&&t[x].r<=r)
	{
		t[x].lazymul*=k;
		t[x].lazymul%=mod;
		t[x].lazyadd*=k;//第一次交题的时候这步操作漏了,打乘法标记的时候记得把加法标记也乘一下
		t[x].lazyadd%=mod;
		t[x].sum[3]*=k*k%mod*k%mod;
		t[x].sum[2]*=k*k%mod;
		t[x].sum[1]*=k;
		t[x].sum[1]%=mod;
		t[x].sum[2]%=mod;
		t[x].sum[3]%=mod;
		return;
	}
	int mid=t[x].l+t[x].r>>1;
	pushdown(x);
	if(l<=mid) mult(ls(x),l,r,k);
	if(r>mid) mult(rs(x),l,r,k);
	pushup(x);
}

void change(int x,int l,int r,long long k)
{
	if(l<=t[x].l&&t[x].r<=r)
	{
		int len=t[x].r-t[x].l+1;
		t[x].lazyset=k,t[x].lazyadd=0,t[x].lazymul=1;
		t[x].sum[3]=len*k%mod*k*k%mod;
		t[x].sum[2]=len*k%mod*k%mod;
		t[x].sum[1]=len*k%mod;
		return;
	}
	int mid=t[x].l+t[x].r>>1;
	pushdown(x);
	if(l<=mid) change(ls(x),l,r,k);
	if(r>mid) change(rs(x),l,r,k);
	pushup(x);
}

long long que(int x,int l,int r,long long p)
{
	if(l<=t[x].l&&t[x].r<=r)
	{
		return t[x].sum[p];
	}
	int mid=t[x].l+t[x].r>>1;
	pushdown(x);
	long long ans=0;
	if(l<=mid) ans+=que(ls(x),l,r,p);
	if(r>mid) ans+=que(rs(x),l,r,p);
	return ans%mod;
}

int main()
{
	while((scanf("%d%d",&n,&m),n||m))
	{
		build(1,1,n);
		int opt,a,b;
		long long c;
		while(m--)
		{
			scanf("%d%d%d%I64d",&opt,&a,&b,&c);//这题是Windows系统
			if(opt==1)
				add(1,a,b,c);
			else if(opt==2)
				mult(1,a,b,c);
			else if(opt==3)
				change(1,a,b,c);
			else if(opt==4)
				printf("%I64d\n",que(1,a,b,c));
		}
	}
	return 0;
}
posted @ 2019-07-30 00:56  wawcac  阅读(164)  评论(0编辑  收藏  举报