把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P3710 方方方的数据结构

题面传送门
有撤销还可以离线。
就显然可以找到每个操作的左右端点。
然后写了线段树分治
这个东西之所以不能线段树分治的原因是因为他是要求顺序的。
所以直接写个高维数据结构即可。
因为不想写kdt所以写了个四分树反正数据随机
code:

#include<cstdio>
#include<vector>
#define N 150000
#define I inline
#define ll long long
#define mod 998244353
using namespace std;
int n,m,k,x,y,z,op[N+5],l[N+5],r[N+5],w[N+5],id[N+5],root;
struct pai{
	ll a,b;
	I int have(){return b||(a^1);}
	pai operator +(const pai &x)const{return (pai){a*x.a%mod,(b*x.a+x.b)%mod};}
}st=(pai){1,0};
struct tree{
	pai f[N+5<<5];int cnt,son[N+5<<5][4];
	I void push(int x,pai w){x&&(f[x]=f[x]+w,0);}
	I void pushdown(int x){if(!f[x].have()) return;for(int i=0;i<=3;i++) push(son[x][i],f[x]);f[x]=st;}
	I void make(int x,int y,int l=1,int ls=n,int r=1,int rs=m,int &now=root){
		!now&&(now=++cnt);f[now]=st;if(l==ls&&r==rs) return;int ml=l+ls>>1,mr=r+rs>>1;
		x<=ml&&(y<=mr?make(x,y,l,ml,r,mr,son[now][0]):make(x,y,l,ml,mr+1,rs,son[now][1]),0);
		x>ml&&(y<=mr?make(x,y,ml+1,ls,r,mr,son[now][2]):make(x,y,ml+1,ls,mr+1,rs,son[now][3]),0);
	}
	I void get(int x,int y,int xs,int ys,pai w,int l=1,int ls=n,int r=1,int rs=m,int now=root){
		if(!now) return;if(x<=l&&ls<=y&&xs<=r&&rs<=ys) return push(now,w);pushdown(now);int ml=l+ls>>1,mr=r+rs>>1;
		if(x<=ml&&xs<=mr) get(x,y,xs,ys,w,l,ml,r,mr,son[now][0]);
		if(x<=ml&&ys>mr) get(x,y,xs,ys,w,l,ml,mr+1,rs,son[now][1]);
		if(y>ml&&xs<=mr) get(x,y,xs,ys,w,ml+1,ls,r,mr,son[now][2]);
		if(y>ml&&ys>mr) get(x,y,xs,ys,w,ml+1,ls,mr+1,rs,son[now][3]);
	}
	I ll find(int x,int y,int l=1,int ls=n,int r=1,int rs=m,int now=root){
		if(l==ls&&r==rs) return f[now].b;pushdown(now);int ml=l+ls>>1,mr=r+rs>>1;
		if(x<=ml)return y<=mr?find(x,y,l,ml,r,mr,son[now][0]):find(x,y,l,ml,mr+1,rs,son[now][1]);
		else return y<=mr?find(x,y,ml+1,ls,r,mr,son[now][2]):find(x,y,ml+1,ls,mr+1,rs,son[now][3]);
	}
}s;
int main(){
	freopen("1.in","r",stdin); freopen("1.out","w",stdout);
	register int i;scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++) scanf("%d",&op[i]),op[i]<=2?(scanf("%d%d%d",&l[i],&r[i],&w[i]),w[i]%=mod):(scanf("%d",&w[i])),id[i]=m;
	for(i=1;i<=m;i++) op[i]==3&&(s.make(w[i],i),0),op[i]==4&&(id[w[i]]=i);
	for(i=1;i<=m;i++){
		op[i]<=2&&(s.get(l[i],r[i],i,id[i],op[i]^1?(pai){w[i],0}:(pai){1,w[i]}),0);
		op[i]==3&&(printf("%lld\n",s.find(w[i],i)));//printf("%lld\n",s.find(2,4));
	} 
}
posted @ 2021-05-03 15:39  275307894a  阅读(58)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end