• 【洛谷3710】方方方的数据结构(四分树)


    点此看题面

    • 给定一个长度为(n)的序列,要求支持四种操作:区间加;区间乘;单点询问;撤销一个操作(即除去这个操作,并保持其他操作间相对顺序不变)。
    • (n,qle1.5 imes10^5),数据随机

    时间轴+四分树

    这种撤销操作的问题一看就非常恐怖,如果用常规的方法去做显然非常困难。

    因此我们考虑时间轴,根据时间轴序列下标这两维建立一个二维坐标系。

    那么一个操作的影响范围就可以表示为一个二维区间。

    容易想到二维线段树,但会被卡空间。由于这道题保证了数据随机,我们可以使用经常遭受迫害的四分树。

    然后这道题实际上有一个非常好的技巧,就是由于询问是单点的,所以有用的叶节点实际上不到(q)个。

    因此我们预先建树,只建出有用的节点,修改时碰上无用节点直接退出。

    这样一棵树的节点个数只有(O(nlogn))个,内存过关了。

    代码:(O(nsqrt n))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 150000
    #define X 998244353
    using namespace std;
    int n,Qt;struct Q {int op,x,l,r,ed;}q[N+5];
    namespace FastIO
    {
    	#define FS 100000
    	#define tc() (FA==FB&&(FB=(FA=FI)+fread(FI,1,FS,stdin),FA==FB)?EOF:*FA++)
    	#define pc(c) (FC==FE&&(clear(),0),*FC++=c)
    	int OT;char oc,FI[FS],FO[FS],OS[FS],*FA=FI,*FB=FI,*FC=FO,*FE=FO+FS;
    	I void clear() {fwrite(FO,1,FC-FO,stdout),FC=FO;}
    	Tp I void read(Ty& x) {x=0;W(!isdigit(oc=tc()));W(x=(x<<3)+(x<<1)+(oc&15),isdigit(oc=tc()));}
    	Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
    	Tp I void writeln(Ty x) {W(OS[++OT]=x%10+48,x/=10);W(OT) pc(OS[OT--]);pc('
    ');}
    }using namespace FastIO;
    int Rt;class QuarterTree
    {
    	private:
    		#define PT CI lx=1,CI rx=Qt,CI ly=1,CI ry=n,int& rt=Rt
    		#define S0 lx,mx,ly,my,O[rt].S[0]
    		#define S1 lx,mx,my+1,ry,O[rt].S[1]
    		#define S2 mx+1,rx,ly,my,O[rt].S[2]
    		#define S3 mx+1,rx,my+1,ry,O[rt].S[3]
    		#define TA(x,v) (O[x].F=(O[x].F+v)%X)
    		#define TM(x,v) (O[x].F=1LL*O[x].F*v%X,O[x].G=1LL*O[x].G*v%X)
    		int Nt;struct node {int F,G,S[4];}O[N*30];
    		I void PD(CI rt)//下传标记
    		{
    			if(O[rt].G^1) {for(RI i=0;i^4;++i) O[rt].S[i]&&TM(O[rt].S[i],O[rt].G);O[rt].G=1;}//先传乘法
    			if(O[rt].F) {for(RI i=0;i^4;++i) O[rt].S[i]&&TA(O[rt].S[i],O[rt].F);O[rt].F=0;}//再传加法
    		}
    	public:
    		I void Bd(CI x,CI y,PT)//建出有用节点
    		{
    			if(!rt&&(O[rt=++Nt].G=1),lx==rx&&ly==ry) return;RI mx=lx+rx>>1,my=ly+ry>>1;
    			x<=mx?(y<=my?Bd(x,y,S0):Bd(x,y,S1)):(y<=my?Bd(x,y,S2):Bd(x,y,S3));
    		}
    		I void A(CI Lx,CI Rx,CI Ly,CI Ry,CI v,PT)//区间加法
    		{
    			if(!rt) return;if(Lx<=lx&&rx<=Rx&&Ly<=ly&&ry<=Ry) return (void)TA(rt,v);
    			PD(rt);RI mx=lx+rx>>1,my=ly+ry>>1;
    			Lx<=mx&&(Ly<=my&&(A(Lx,Rx,Ly,Ry,v,S0),0),Ry>my&&(A(Lx,Rx,Ly,Ry,v,S1),0));
    			Rx>mx&&(Ly<=my&&(A(Lx,Rx,Ly,Ry,v,S2),0),Ry>my&&(A(Lx,Rx,Ly,Ry,v,S3),0));
    		}
    		I void M(CI Lx,CI Rx,CI Ly,CI Ry,CI v,PT)//区间乘法
    		{
    			if(!rt) return;if(Lx<=lx&&rx<=Rx&&Ly<=ly&&ry<=Ry) return (void)TM(rt,v);
    			PD(rt);RI mx=lx+rx>>1,my=ly+ry>>1;
    			Lx<=mx&&(Ly<=my&&(M(Lx,Rx,Ly,Ry,v,S0),0),Ry>my&&(M(Lx,Rx,Ly,Ry,v,S1),0));
    			Rx>mx&&(Ly<=my&&(M(Lx,Rx,Ly,Ry,v,S2),0),Ry>my&&(M(Lx,Rx,Ly,Ry,v,S3),0));
    		}
    		I int Q(CI x,CI y,PT)//单点询问
    		{
    			if(lx==rx&&ly==ry) return O[rt].F;PD(rt);RI mx=lx+rx>>1,my=ly+ry>>1;
    			return x<=mx?(y<=my?Q(x,y,S0):Q(x,y,S1)):(y<=my?Q(x,y,S2):Q(x,y,S3));
    		}
    }T;
    int main()
    {
    	RI i;for(read(n,Qt),i=1;i<=Qt;++i) switch(read(q[i].op),q[i].op)
    	{
    		case 1:case 2:read(q[i].l,q[i].r,q[i].x),q[i].ed=Qt;break;//初始化时间轴上右端点为Qt
    		case 3:read(q[i].x),T.Bd(i,q[i].x);break;case 4:read(q[i].x),q[q[i].x].ed=i;break;//撤销看成设定对应操作时间轴上的右端点
    	}
    	for(i=1;i<=Qt;++i) switch(q[i].op)
    	{
    		case 1:T.A(i,q[i].ed,q[i].l,q[i].r,q[i].x);break;case 2:T.M(i,q[i].ed,q[i].l,q[i].r,q[i].x);break;//二维区间修改
    		case 3:writeln(T.Q(i,q[i].x));break;//单点询问
    	}return clear(),0;
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    cqyz oj | 单峰排列
    cqyz oj/uva 548 | 二叉树
    cqyz oj | 树网的核 | 树的直径
    cqyz oj | 树上的询问 | 最近公共祖先
    cqyz oj | 循环逆序对 | 逆序对 | 树状数组
    cqyz oj | 潜水比赛 | 贪心
    YOLO v3 & Pascal VOC数据集
    太阳爆发分类
    PPT制作
    anaconda
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu3710.html
Copyright © 2020-2023  润新知