• luoguP3710 方方方的数据结构 KDtree


    刚开始看到这道题的时候想的是线段树分治,毕竟这里的乘法和加法都是可以撤销的.   

    但是后来发现如果想要线段树分治的话就必须要满足交换律,但是标记 $(x,y)$ ( 乘 $x$ 后加 $y$)只满足结合律,不满足交换律.      

    那么就考虑 kdtree.   

    kdtree 是维护平面上点的数据结构,然后我们可以把每个询问抽象成点 $(t_{i},x_{i})$ 表示时间轴和坐标轴.     

    那么每一次的修改就可以表示成平面上的一个矩阵了,只需在 kdtree 上维护一个标记就行.     

    在查询的时候我的做法是暴力跳父亲节点,单次复杂度是 $O($kdtree树高$)$.

    code: 

    #include <bits/stdc++.h>    
    #define N 160000   
    #define ll long long 
    #define mod 998244353 
    #define lson s[now].ch[0] 
    #define rson s[now].ch[1]   
    #define setIO(s) freopen(s".in","r",stdin) 
    using namespace std;
    int d,n,m; 
    int last[N],L[N],R[N],cur[N],GE[N];           
    struct Tag 
    {
    	int x,y;   
    	Tag(int a=1,int b=0){ x=a,y=b; }             
    	Tag operator+(const Tag b) const 
    	{
    		Tag c;    
    		c.x=(ll)x*b.x%mod;    
    		c.y=(ll)((ll)y*b.x%mod+b.y)%mod;    
    		return c;   
    	}
    	void init(int a=1,int b=0) { x=a,y=b; }     
    }ope[N];   
    struct data 
    {
    	Tag h;    
    	int ch[2],p[2],mi[2],ma[2],f,val,id;                  
    	bool operator<(const data b) const 
    	{
    		return p[d]==b.p[d]?p[d^1]<b.p[d^1]:p[d]<b.p[d];   
    	}
    	int isin(data b) 
    	{
    		int fl=1;  
    		for(int i=0;i<2;++i) 
    			if(mi[i]<b.mi[i]||ma[i]>b.ma[i]) fl=0;
    		return fl;   
    	}
    	int isout(data b) 
    	{
    		int fl=0;   
    		for(int i=0;i<2;++i) 
    			if(mi[i]>b.ma[i]||ma[i]<b.mi[i]) fl=1;   
    		return fl;    
    	}
    }s[N];            
    void pushup(int x,int y) 
    {
    	for(int i=0;i<2;++i) 
    	{
    		s[x].mi[i]=min(s[x].mi[i],s[y].mi[i]);   
    		s[x].ma[i]=max(s[x].ma[i],s[y].ma[i]);   
    	}
    }
    int build(int l,int r,int o) 
    {  
    	int mid=(l+r)>>1;  
    	d=o,nth_element(s+l,s+mid,s+1+r);     
    	for(int i=0;i<2;++i) 
    		s[mid].mi[i]=s[mid].ma[i]=s[mid].p[i]; 
    	s[mid].val=0;        
    	s[mid].h.init();    
    	GE[s[mid].id]=mid;    
    	if(mid>l) 
    	{
    		s[mid].ch[0]=build(l,mid-1,o^1);    
    		s[s[mid].ch[0]].f=mid;    
    		pushup(mid,s[mid].ch[0]);  
    	}
    	if(r>mid) 
    	{
    		s[mid].ch[1]=build(mid+1,r,o^1);    
    		s[s[mid].ch[1]].f=mid;   
    		pushup(mid,s[mid].ch[1]);   
    	}
    	return mid;   
    }
    void mark(int x,Tag v) 
    {
    	s[x].h=s[x].h+v;     
    	s[x].val=(ll)((ll)s[x].val*v.x%mod+v.y)%mod;               
    }
    void pushdown(int now) 
    {
    	if(lson) mark(lson,s[now].h);   
    	if(rson) mark(rson,s[now].h);  
    	s[now].h.init();   
    }
    void update(int now,data p,Tag v) 
    {
    	if(s[now].isout(p)) return;    
    	if(s[now].isin(p)) 
    	{
    		mark(now,v);    
    		return;    
    	}
    	if(s[now].p[0]>=p.mi[0]&&s[now].p[0]<=p.ma[0]&&s[now].p[1]>=p.mi[1]&&s[now].p[1]<=p.ma[1]) 
    		s[now].val=(ll)((ll)s[now].val*v.x%mod+v.y)%mod;    
    	pushdown(now);            
    	if(lson) update(lson,p,v);  
    	if(rson) update(rson,p,v);    
    }                             
    int main() 
    {
    	// setIO("input"); 
    	scanf("%d%d",&n,&m); 
    	int x,y,z,o,cnt=0;         
    	for(int i=1;i<=m;++i) 
    	{
    		scanf("%d",&o);    
    		cur[i]=o;     
    		if(o<=2) 
    		{
    			last[i]=m;  
    			scanf("%d%d%d",&L[i],&R[i],&z);      
    			if(o==1) ope[i].x=1,ope[i].y=z%mod;   
    			if(o==2) ope[i].x=z%mod,ope[i].y=0; 
    		}          
    		else 
    		{ 
    			scanf("%d",&x);  
    			if(o==3) 
    			{
    				++cnt;    
    				s[cnt].p[0]=i;  
    				s[cnt].p[1]=x;     
    				s[cnt].id=i;                     
    			}
    			if(o==4)  last[x]=i-1;        
    		}
    	}
    	data tmp;  
    	int root=build(1,cnt,0);     
        for(int i=1;i<=m;++i) 
        {
        	if(cur[i]<=2) 
        	{
        		tmp.mi[0]=i,tmp.ma[0]=last[i];        
        		tmp.mi[1]=L[i],tmp.ma[1]=R[i];         
        		update(root,tmp,ope[i]);         
        	}       
        	if(cur[i]==3) 
        	{
        		x=GE[i];     
        		Tag c(1,0);    
        		for(int j=s[x].f;j;j=s[j].f)    
        			c=c+s[j].h;     
        		printf("%d
    ",(ll)((ll)s[x].val*c.x%mod+c.y)%mod);        
        	}
        }
    	return 0;
    }
    

      

  • 相关阅读:
    BLE 5协议栈-安全管理层
    BLE 5协议栈-通用属性规范层(GATT)
    BLE 5协议栈-属性协议层(ATT)
    BLE 5协议栈-逻辑链路控制与适配协议层(L2CAP)
    BLE 5协议栈-主机控制接口(HCI)
    BLE 5协议栈-直接测试模式
    BLE 5协议栈-链路层
    BLE 5协议栈-物理层
    名词缩写
    C#中数据库事务、存储过程基本用法
  • 原文地址:https://www.cnblogs.com/guangheli/p/13254973.html
Copyright © 2020-2023  润新知