#206. round

这道题的做法有很多。

先讲一种最好理解的算法:O(n^2)暴力修改、O(n^2)暴力询问,期望得分30,实际得分100。。。

一看就是不负责任的XX哥gen的数据。——Scarlet

ljg告诉我,这题只用写300B,然而我满脑子线段树,还是选择了自己的SB算法。

然后第二种,线段树+哈希,nlogn直接过。

第三种,某蒟蒻并没有想到直接判query(l,r-c)==query(l+c,r),然后就用了倍增处理,然后就挂了QAQ。

“这是我见过最傻逼的人。”wamach对镜子说。

奇丑无比的代码:

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define rep(i,j,k) for(i=j;i<=k;i++)
#define per(i,j,k) for(i=j;i>=k;i--)
const int N=100005;
int n,m,k,T[N<<2],lz[N<<2],bin[N],Sb[N];char s[N];
void pd(int l,int r,int num){
	if(!lz[num])return;
	if(l==r)T[num]=lz[num];
	else{
		lz[num<<1]=lz[num<<1|1]=lz[num];
		T[num]=Sb[r-l]*lz[num];
	}
	lz[num]=0;
}
void up(int l,int mid,int r,int num){
	pd(l,mid,num<<1);pd(mid+1,r,num<<1|1);
	T[num]=T[num<<1]*bin[r-mid]+T[num<<1|1];
}
void build(int l,int r,int num){
	if(l==r){
		T[num]=s[l]-'/';return;
	}
	int mid=l+r>>1;
	build(l,mid,num<<1);
	build(mid+1,r,num<<1|1);
	up(l,mid,r,num);
}
void modify(int x,int L,int R,int l,int r,int num){
	int mid=l+r>>1;
	if(L<=l&&r<=R){
		lz[num]=x+1;pd(l,r,num);return;
	}
	pd(l,r,num);
	if(L<=mid)modify(x,L,R,l,mid,num<<1);
	if(R>mid)modify(x,L,R,mid+1,r,num<<1|1);
	up(l,mid,r,num);
}
int query(int L,int R,int l,int r,int num){
	int mid=l+r>>1;pd(l,r,num);
	if(L<=l&&r<=R)return T[num];
	int rtn=0;
	if(R<=mid)return query(L,R,l,mid,num<<1);
	if(L>mid)return query(L,R,mid+1,r,num<<1|1);
	return query(L,mid,l,mid,num<<1)*bin[R-mid]+query(L,R,mid+1,r,num<<1|1);
}
int main(){
//	freopen("w.out","w",stdout);
	int i,o,x,y,yy,z,tmp[20],ln,u,v;
	scanf("%d%d%d%s",&n,&m,&k,s+1);
	bin[0]=Sb[0]=1;
	rep(i,1,n){
		bin[i]=bin[i-1]*11;Sb[i]=Sb[i-1]+bin[i];
	}
	build(1,n,1);
	for(m+=k;m--;){
		scanf("%d%d%d%d",&o,&x,&y,&z);
		if(o==1)modify(z,x,y,1,n,1);
		else{
			if(!z){puts("YES");continue;}
			yy=y;y-=(y-x+1)%z;
			tmp[ln=1]=query(u=x,v=x+z-1,1,n,1);
			for(z<<=1;(v=x+z-1)<=y;z<<=1){
				tmp[++ln]=query(u,v,1,n,1);
				if(tmp[ln]!=tmp[ln-1]*(bin[z>>1]+1))break;
			}
			if(v<=y){puts("NO");continue;}
			u+=z>>1;
			for(z>>=2;u<=y;u=v+1,z>>=1){
				for(--ln;(v=u+z-1)>y;)z>>=1,--ln;
				if(tmp[ln]!=query(u,v,1,n,1))break;
			}
			if(u<=y){puts("NO");continue;}
			puts(yy==y||query(y+1,yy,1,n,1)==query(x,x+yy-y-1,1,n,1)?"YES":"NO");
		}
	}
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值