zoukankan      html  css  js  c++  java
  • CF817F MEX Queries

    前言

    其实本来是用来练习线段树上二分的。
    结果这个懒标记互相覆盖和累加的性质搞了我好久(虽然只是个板子
    一开始WA on #8 死活调不过。
    重构了一遍才过。

    题解

    详见:https://www.luogu.com.cn/blog/184549/solution-cf817f

    就是对懒标记下传时分类讨论。
    如果是区间赋值/清零就可以直接覆盖。

    如果是区间反转就根据原来的懒标记分类讨论:

    • 原来是区间赋值,改成区间清零。
    • 原来是区间清零,改成区间赋值。
    • 原来是区间反转,改成啥也不干。
    • 原来是啥也不干,改成区间反转。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define FCC fclose(stdin),fclose(stdout)
    #define ls (k<<1)
    #define rs (k<<1|1)
    #define mid ((l+r)>>1)
    const int INF = 0x3f3f3f3f,N = 4e5+10;
    inline ll read()
    {
    	ll ret=0;char ch=' ',c=getchar();
    	while(!(c>='0'&&c<='9')) ch=c,c=getchar();
    	while(c>='0'&&c<='9') ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
    	return ch=='-'?-ret:ret;
    }
    int n,tot;
    struct ask
    {
    	int op;
    	ll l,r;	
    }q[N];
    ll p[N<<1],a[N<<1],cnt;
    ll rnk[N<<1];
    struct Segtree
    {
    	int sum[N<<2];
    	int lazy[N<<2];
    	void init_lazy(){memset(lazy,-1,sizeof(lazy));}
    	inline void add(int k,int l,int r,int v)
    	{
    		//lazy/vl:初始-1,区间覆盖1,区间清除0
    		//rev/vr: 初始0,区间反转1  
    		if(v==1||v==0) lazy[k]=v,sum[k]=(r-l+1)*v;
    		else 
    		{
    			sum[k]=r-l+1-sum[k];
    			if(lazy[k]==-1) lazy[k]=v;
    			else if(lazy[k]==1) lazy[k]=0;
    			else if(!lazy[k]) lazy[k]=1;
    			else lazy[k]=-1;
    		}
    	}
    	inline void pushdown(int k,int l,int r)
    	{
    		if(lazy[k]==-1) return;
    		add(ls,l,mid,lazy[k]);
    		add(rs,mid+1,r,lazy[k]);
    		lazy[k]=-1; 
    	}
    	void modify(int k,int l,int r,int x,int y,int vl)
    	{		
    		if(x<=l&&r<=y) {add(k,l,r,vl);return;}
    		pushdown(k,l,r);
    		if(x<=mid) modify(ls,l,mid,x,y,vl);
    		if(y>mid)  modify(rs,mid+1,r,x,y,vl);
    		sum[k]=sum[ls]+sum[rs];
    	}
    	int find(int k,int l,int r,int x,int y)
    	{
    		if(sum[k]==r-l+1) return 0;
    		if(!sum[k]) return l;
    		pushdown(k,l,r);
    		int ret=find(ls,l,mid,x,y);
    		if(ret) return ret;
    		return find(rs,mid+1,r,x,y);
    	}
    }str;
    void discrete()
    {
    	sort(p+1,p+cnt+1);
    	tot=unique(p+1,p+cnt+1)-p-1;
    	for(int i=1;i<=cnt;i++)
    	{
    		int newl=lower_bound(p+1,p+tot+1,a[i])-p;
    	//	printf("new %d:[%d,%d]\n",i,newl,newr);
    		rnk[newl]=a[i];
    	}
    	for(int i=1;i<=n;i++)
    	{
    		int newl=lower_bound(p+1,p+tot+1,q[i].l)-p;
    		int newr=lower_bound(p+1,p+tot+1,q[i].r)-p;	
    	//	printf("new %d:[%d,%d]\n",i,newl,newr);
    		q[i].l=newl,q[i].r=newr;
    	}
    	return;
    }
    void work()
    {
    	str.init_lazy();
    	for(int i=1;i<=n;i++)	
    	{
    		if(q[i].op==1)	   //区间赋值 
    			str.modify(1,1,tot,q[i].l,q[i].r,1);
    		else if(q[i].op==2)//区间清零 
    			str.modify(1,1,tot,q[i].l,q[i].r,0);
    		else 			   //区间反转 
    			str.modify(1,1,tot,q[i].l,q[i].r,2);
    		int pos=str.find(1,1,tot,q[i].l,q[i].r);
    	//	printf("pos=%d\n",pos);
    	//	if(!pos) printf("%lld\n",rnk[tot]+1); 
    		printf("%lld\n",rnk[pos]);
    	}
    }
    int main()
    {
    	n=read();
    	cnt++,p[cnt]=a[cnt]=1; 
    	for(int i=1;i<=n;i++) 
    		q[i].op=read(),
    		cnt++,p[cnt]=a[cnt]=q[i].l=read(),
    		cnt++,p[cnt]=a[cnt]=q[i].r=read(),
    		cnt++,p[cnt]=a[cnt]=q[i].r+1;
    	discrete();
    	work();
    	return 0;
    }
    
  • 相关阅读:
    操作系统——第四章 文件管理
    操作系统——第三章 内存管理
    操作系统——第二章 进程管理
    last-child到底怎么用
    Https个人总结
    白话https
    RSA算法
    算法导论笔记:11散列表(哈希表)
    算法导论笔记:10基本数据结构(番外)
    算法导论笔记:09中位数和顺序统计量
  • 原文地址:https://www.cnblogs.com/conprour/p/15564036.html
Copyright © 2011-2022 走看看