zoukankan      html  css  js  c++  java
  • #离线,倒序,线段树#Comet OJ

    题目

    初始时有 (N) 个空的栈,编号为 (1 sim N),有以下三种类型的指令:

    push (L) (R) (v):把编号 (L sim R) 这连续 (R-L+1) 个栈都 push 一个数 (v)

    pop (L) (R):把编号 (L sim R) 这连续 (R-L+1) 个栈都执行 pop 一次,保证进行此指令时,这 (R-L+1) 个栈都不为空。

    find (id) (pos):询问第 (id) 个栈由栈顶数来第 (pos) 个数字是什么,保证进行此指令时,第 (id) 个栈至少有 (pos) 个数字。

    输入会给你总共 (Q) 个指令,对于每个 find 指令请输出正确答案。

    (1 le N, Q le 2 imes 10^5)


    分析

    正着模拟不好做,考虑倒着做,第(pos)个数字也就意味着在它之前的第(pos)有效插入即为答案,
    那么给每个询问设计倒计时,(push)(pop)就转换成区间加问题,当整体最小值为0时记录该询问的答案


    代码

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define rr register
    using namespace std;
    const int N=200011,inf=1e7;
    struct rec{int x,y,z,w;}b[N],q[N];
    int n,m,Q,ans[N],l[N],r[N],T,rk[N],w[N<<2],lazy[N<<2],p[N<<2];
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(int ans){
        if (ans>9) print(ans/10);
    	putchar(ans%10+48); 
    }
    inline signed min(int a,int b){return a<b?a:b;}
    inline signed max(int a,int b){return a>b?a:b;}
    bool cmp(int x,int y){return b[x].x<b[y].x;}
    inline void build(int k,int l,int r){
    	w[k]=inf;
    	if (l==r) {p[k]=l; return;}
    	rr int mid=(l+r)>>1;
    	build(k<<1,l,mid);
    	build(k<<1|1,mid+1,r);
    	p[k]=w[k<<1]<w[k<<1|1]?p[k<<1]:p[k<<1|1];
    }
    inline void update(int k,int l,int r,int x,int y,int z){
    	if (l==x&&r==y) {w[k]+=z,lazy[k]+=z; return;}
    	rr int mid=(l+r)>>1;
    	if (lazy[k]){
    		lazy[k<<1]+=lazy[k],lazy[k<<1|1]+=lazy[k],
    		w[k<<1]+=lazy[k],w[k<<1|1]+=lazy[k],lazy[k]=0;
    	}
    	if (y<=mid) update(k<<1,l,mid,x,y,z);
        else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
            else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
        p[k]=w[k<<1]<w[k<<1|1]?p[k<<1]:p[k<<1|1];
        w[k]=min(w[k<<1],w[k<<1|1]);
    }
    inline void upd(int k,int l,int r,int x,int y){
    	if (l==r) {w[k]=y; return;}
    	rr int mid=(l+r)>>1;
    	if (lazy[k]){
    		lazy[k<<1]+=lazy[k],lazy[k<<1|1]+=lazy[k],
    		w[k<<1]+=lazy[k],w[k<<1|1]+=lazy[k],lazy[k]=0;
    	}
    	if (x<=mid) upd(k<<1,l,mid,x,y);
    	    else upd(k<<1|1,mid+1,r,x,y);
    	p[k]=w[k<<1]<w[k<<1|1]?p[k<<1]:p[k<<1|1];
        w[k]=min(w[k<<1],w[k<<1|1]);
    }
    signed main(){
    	n=iut(),T=iut();
    	for (rr int i=1;i<=T;++i){
    		rr char c=getchar();
    		while (!isalpha(c)) c=getchar();
    		c=getchar();
    		rr int x=iut(),y=iut();
    		switch (c){
    			case 'u':{
    				q[++Q]=(rec){x,y,-1,iut()};
    				break;
    			}
    			case 'o':{
    				q[++Q]=(rec){x,y,1,-1};
    				break;
    			}
    			case 'i':{
    				++m,b[m]=(rec){x,y,0,Q};
    				break;
    			}
    		}
    	}
    	for (rr int i=1;i<=m;++i) rk[i]=i;
    	sort(rk+1,rk+1+m,cmp);
    	for (rr int i=1;i<=m;++i) b[rk[i]].z=i;
    	for (rr int i=1;i<=n;++i) l[i]=m+1;
    	for (rr int i=1;i<=m;++i)
    		l[b[rk[i]].x]=min(l[b[rk[i]].x],i),
    		r[b[rk[i]].x]=max(r[b[rk[i]].x],i);
    	for (rr int i=n;i>1;--i) l[i-1]=min(l[i-1],l[i]);
    	for (rr int i=2;i<=n;++i) r[i]=max(r[i],r[i-1]);
    	build(1,1,m);
    	for (rr int i=Q,j=m;i;--i){
    		for (;b[j].w==i;--j) upd(1,1,m,b[j].z,b[j].y);
    		if (l[q[i].x]<=r[q[i].y]) update(1,1,m,l[q[i].x],r[q[i].y],q[i].z);
    		while (!w[1]) ans[rk[p[1]]]=q[i].w,upd(1,1,m,p[1],inf);
    	}
    	for (rr int i=1;i<=m;++i) print(ans[i]),putchar(10);
    	return 0;
    }
    
  • 相关阅读:
    使用C#实现DHT磁力搜索的BT种子后端管理程序+数据库设计(开源)
    便携版WinSCP在命令行下同步文件夹
    ffmpeg (ffprobe)分析文件关键帧时间点
    sqlite删除数据或者表后,回收数据库文件大小
    ubuntu 20.04下 freeswitch 配合 fail2ban 防恶意访问
    ffmpeg使用nvenc编码的结论记录
    PC版跑跑卡丁车 故事模式 亚瑟传说章节 卡美洛庆典 2阶段 心灵之眼 攻略
    There was an error loading or playing the video
    Nvidia RTX Voice 启动报错修复方法
    火狐浏览器 关闭跨域限制
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14979890.html
Copyright © 2011-2022 走看看