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;
    }
    
  • 相关阅读:
    拖动内容,滚动条滚动,横向
    前端面试题及答案整理(一)
    微软拼音转换工具类ChnCharInfo.dll
    table表格,让thead固定,tbody有滚动条,关键是都对齐的纯css写法。
    [C#]_[使用微软OpenXmlSDK (OpenXmlReader)读取xlsx表格] 读取大数据量100万条数据Excel文件解决方案
    asp.net mvc Post上传文件大小限制
    .net OADate 转javascript的Datetime js 5位 日期 转换
    在.NET开发中的单元测试工具之(1)——NUnit
    在.NET开发中的单元测试工具之(2)——xUnit.Net
    Git 头像修改 原
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14979890.html
Copyright © 2011-2022 走看看