zoukankan      html  css  js  c++  java
  • [uoj218]火车管理——主席树

    题目大意

    维护一个栈,每次区间压栈,单点弹栈,区间询问栈顶的元素和。

    思路

    如果没有弹栈的操作的话,我们每一次只需要在一颗线段树上面区间赋值即可。

    加上弹栈操作,我们每次就需要知道当前栈顶元素的上一个元素是什么,考虑用主席树来维护每一个时刻每一个位置的最近一次的修改位置。

    假设当前的时间为x且我们需要弹栈,那么我们需要先查询得到最近的一次时间y,然后查询y-1的修改时间z,那么我们就得到了栈顶下面的元素的修改时间。

    然后我们需要将x点的这个元素的时间改为z,然后更新查询线段树上的答案即可。

    不难发现我们实际上是向前维护了一个最近修改时间的链表,由于主席树的继承性质,直接查询y-1使得我们的答案是正确的。

    /*=======================================
     * Author : ylsoi
     * Time : 2019.3.10
     * Problem : uoj218
     * E-mail : ylsoi@foxmail.com
     * ====================================*/
    #include<bits/stdc++.h>
    
    #define REP(i,a,b) for(int i=a,i##_end_=b;i<=i##_end_;++i)
    #define DREP(i,a,b) for(int i=a,i##_end_=b;i>=i##_end_;--i)
    #define debug(x) cout<<#x<<"="<<x<<" "
    #define fi first
    #define se second
    #define mk make_pair
    #define pb push_back
    #define mid ((l+r)>>1)
    typedef long long ll;
    
    using namespace std;
    
    void File(){
    	freopen("uoj218.in","r",stdin);
    	freopen("uoj218.out","w",stdout);
    }
    
    template<typename T>void read(T &_){
    	_=0; T f=1; char c=getchar();
    	for(;!isdigit(c);c=getchar())if(c=='-')f=-1;
    	for(;isdigit(c);c=getchar())_=(_<<1)+(_<<3)+(c^'0');
    	_*=f;
    }
    
    string proc(){
    	ifstream f("/proc/self/status");
    	return string(istreambuf_iterator<char>(f),istreambuf_iterator<char>());
    }
    
    const int maxn=5e5+10;
    int n,m,ty,ans,root[maxn],tot,w[maxn];
    
    struct Segment_Tree{
    #define lc o<<1
    #define rc o<<1|1
    #define lson lc,l,mid
    #define rson rc,mid+1,r
    	int val[maxn<<2],sum[maxn<<2],las[maxn<<2];
    	void pushdown(int o,int l,int r){
    		if(las[o])las[lc]=las[rc]=las[o],las[o]=0;
    		if(val[o]){
    			val[lc]=val[rc]=val[o];
    			sum[lc]=(mid-l+1)*val[o];
    			sum[rc]=(r-mid)*val[o];
    			val[o]=0;
    		}
    	}
    	void update(int o,int l,int r,int L,int R,int x,int y){
    		if(L<=l && r<=R)val[o]=x,sum[o]=(r-l+1)*x,las[o]=y;
    		else{
    			pushdown(o,l,r);
    			if(L<=mid)update(lson,L,R,x,y);
    			if(R>=mid+1)update(rson,L,R,x,y);
    			sum[o]=sum[lc]+sum[rc];
    		}
    	}
    	int query_sum(int o,int l,int r,int L,int R){
    		if(L<=l && r<=R)return sum[o];
    		else{
    			pushdown(o,l,r);
    			int ret=0;
    			if(L<=mid)ret+=query_sum(lson,L,R);
    			if(R>=mid+1)ret+=query_sum(rson,L,R);
    			return ret;
    		}
    	}
    	int query_las(int o,int l,int r,int p){
    		if(l==r)return las[o];
    		pushdown(o,l,r);
    		if(p<=mid)return query_las(lson,p);
    		else return query_las(rson,p);
    	}
    #undef lc
    #undef rc
    }T1;
    
    struct Chairman_Tree{
    	int cnt;
    	struct node{int val,lc,rc;}t[maxn*120];
    	void insert(int &o,int l,int r,int L,int R,int x){
    		int now=++cnt;
    		t[now]=t[o],o=now,t[o].val=x;
    		if(L<=l && r<=R)t[o].lc=t[o].rc=(l==r ? 0 : o);
    		else{
    			if(L<=mid)insert(t[o].lc,l,mid,L,R,x);
    			if(R>=mid+1)insert(t[o].rc,mid+1,r,L,R,x);
    		}
    	}
    	int query(int o,int l,int r,int p){
    		if(l==r)return t[o].val;
    		if(p<=mid)return query(t[o].lc,l,mid,p);
    		else return query(t[o].rc,mid+1,r,p);
    	}
    }T2;
    
    int main(){
    	//File();
    
    	read(n),read(m),read(ty);
    
    	int op,l,r,x;
    
    	/*T1.update(1,1,n,1,2,1,1);
    	cout<<T1.query_sum(1,1,n,4,5)<<endl;
    	REP(i,1,n)printf("%d ",T1.query_sum(1,1,n,i,i));
    	printf("
    ");*/
    
    	REP(i,1,m){
    		read(op);
    		if(op==1){
    			read(l),read(r);
    			l=(l+ans*ty)%n+1;
    			r=(r+ans*ty)%n+1;
    			if(l>r)swap(l,r);
    			printf("%d
    ",ans=T1.query_sum(1,1,n,l,r));
    		}
    		else if(op==2){
    			read(l);
    			l=(l+ans*ty)%n+1;
    			int tim=T1.query_las(1,1,n,l);
    			if(tim){
    				int las=T2.query(root[tim-1],1,n,l);
    				++tot;
    				root[tot]=root[tot-1];
    				T2.insert(root[tot],1,n,l,l,las);
    				T1.update(1,1,n,l,l,w[las],las);
    			}
    		}
    		else{
    			read(l),read(r),read(x);
    			l=(l+ans*ty)%n+1;
    			r=(r+ans*ty)%n+1;
    			if(l>r)swap(l,r);
    			w[++tot]=x;
    			root[tot]=root[tot-1];
    			T2.insert(root[tot],1,n,l,r,tot);
    			T1.update(1,1,n,l,r,x,tot);
    		}
    		/*REP(j,1,n)printf("%d ",T1.query_sum(1,1,n,j,j));
    		printf("
    ");*/
    	}
    
    	//cerr<<proc()<<endl;
    
    	return 0;
    }
    
    
  • 相关阅读:
    vue-cli3 set vue.config.js
    oracle 基本查询语句及实例
    输出流啊输入流
    java线程
    sql基础
    抽象类和接口
    重载和重写的区别
    简单的java面向对象计算器
    运算符的优先级
    隐式类型转换规则
  • 原文地址:https://www.cnblogs.com/ylsoi/p/10513455.html
Copyright © 2011-2022 走看看