HihoCoder - 1058

考场上看到这题以为splay于是跳过了= =,之后尝试自己写然而并是想不清楚关于3种tag的传递,WAWAWAWAWA,于是拿出qt的标程开始改自己的代码,然后二分查错。。。其实传递没那么复杂。。。染色tag时,把加法和等差数列的tag都清除,之后如果有加法或等差数列tag要打,那就和染色tag并存,向下穿tag时,先传染色tag,再传其他的,因为等差加和全加的tag,相当于覆盖在之前已经有的染色tag上的tag。

有一个技巧就是,因为线段树的遍历是按照前后顺序来的,于是等差数列的首项直接用全局变量delta来表示,打上一个tag之后直接delta加上这段的值,到达下一个位置的首项的值。

#include<cstdio>
#include<cstring>
#define maxl 50010
#define ls(x) x<<1
#define rs(x) x<<1|1
#define MOD 26

int n,m,head,key,x,y,z,a[maxl],delta,K,L,R,LL,RR;
int leaf[maxl];
char c;
struct node
{
	int same,add,del,ins;//bian jia dengcha
}t[maxl<<2];

inline void build(int l,int r,int k)
{
	if(l==r)
	{
		t[k].same=a[l];
		leaf[l]=k;
		return;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls(k));build(mid+1,r,rs(k));
	t[k].same=-1;
}

inline void downtag(int l,int r,int k)
{
	if(!t[k].add && !t[k].del && !t[k].ins && t[k].same==-1)
		return;
	int mid=(l+r)>>1;
	if(t[k].same!=-1)
	{
		t[ls(k)].same=t[rs(k)].same=t[k].same;
		t[ls(k)].add=t[ls(k)].del=t[ls(k)].ins=0;
		t[rs(k)].add=t[rs(k)].del=t[rs(k)].ins=0;
	}
	if(t[k].add)
	{
		t[ls(k)].add+=t[k].add;t[ls(k)].add%=MOD;
		t[rs(k)].add+=t[k].add;t[rs(k)].add%=MOD;
	}
	if(t[k].del !=0 || t[k].ins!=0)
	{
		t[ls(k)].del+=t[k].del;t[ls(k)].ins+=t[k].ins;
		t[ls(k)].del%=MOD;t[ls(k)].ins%=MOD;
		t[rs(k)].del+=t[k].del+(mid-l+1)*t[k].ins;t[rs(k)].ins+=t[k].ins;
		t[rs(k)].del%=MOD;t[rs(k)].ins%=MOD;
	}
	t[k].add=t[k].del=t[k].ins=0;
	t[k].same=-1;
}

inline void ask(int l,int r,int k)
{
	if(LL<=l && r<=RR)
	{
		if(key==1)
		{
			t[k].same=K;t[k].add=t[k].del=t[k].ins=0;
			return;
		}
		if(key==2)
		{
			t[k].add+=K;t[k].add%=MOD;
			return;
		}
		if(key==4)
		{
			t[k].del+=delta;t[k].del%=MOD;
			t[k].ins++;t[k].ins%=MOD;
			delta+=r-l+1;delta%=MOD;
			return;
		}
	}
	int mid=(l+r)>>1;
	downtag(l,r,k);
	if(LL<=mid)
		ask(l,mid,ls(k));
	if(mid<RR)
		ask(mid+1,r,rs(k));
}

inline void down(int l,int r,int k)
{
	if(l==r)
	{
		a[l]=t[k].same;
		a[l]+=t[k].add;a[l]%=MOD;
		a[l]+=t[k].del;a[l]%=MOD;
		return;
	}
	downtag(l,r,k);
	int mid=(l+r)>>1;
	down(l,mid,ls(k));
	down(mid+1,r,rs(k));
}

int main()
{
	scanf("%d%d",&n,&m);
	getchar();
	for(int i=1;i<=n;i++)
	{
		c=getchar();
		a[i]=c-'A';
	}
	getchar();
	build(1,n,1);
	for(int i=1;i<=m;i++)
	{
		getchar();getchar();getchar();
		scanf("%d",&key);
		if(key==3)
		{
			scanf("%d\n",&K);
			head+=K;
			while(head>n)
				head-=n;
			continue;
		}
		scanf("%d%d",&L,&R);
		if(key==1)
		{
			getchar();c=getchar();
			K=c-'A';
		}
		else
			if(key==2)
				scanf("%d",&K);
		getchar();
		L=L+head;R=R+head;delta=1;
		while(L>n)
			L-=n;
		while(R>n)
			R-=n;
		if(L<=R)
		{
			LL=L;RR=R;
			ask(1,n,1);
		}
		else
		{
			LL=L;RR=n;ask(1,n,1);
			LL=1;RR=R;ask(1,n,1);
		}
	}
	down(1,n,1);
	for(int i=1+head;i<=n;i++)
		printf("%c",a[i]+'A');
	for(int i=1;i<=head;i++)
		printf("%c",a[i]+'A');
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值