題目鏈接:點擊查看
題目大意:初始時有一個空的集合,需要執行 n 次操作:
1 l r:將區間 [ l , r ] 內未出現的數加入到集合中2 l r:將區間 [ l , r ] 內出現的數字全部刪除3 l r:將區間 [ l , r ] 內未出現的數加入到集合中,同時將區間 [ l , r ] 內出現過的數字全部刪除
每次操作后取集合的 MEX
題目分析:HDU - 3397?的弱化版
簡化版題意就是,初始時有一個全 0 的序列,操作 1 是將區間內的數全部修改為 1,操作 2 是將區間內的數全部修改為 0,操作 3 是將區間內的數全部置反,即 0 變為 1,1 變為 0,每次詢問需要回答從左側開始首次出現的 0 的位置,三個操作其實就是一個比較基礎的 lazy 序的實現,一個控制區間覆蓋,一個控制區間翻轉,而對于每次詢問只需要在線段樹上行整體二分就可以輕松得到答案了
需要注意的是因為區間范圍非常的大,所以需要離線去做,先將區間離散化一下,因為對于某段操作 [ l , r ] 來說,只會影響到 l - 1 和 r + 1 ,所以離散化的時候多離散化幾個點就好了
代碼:
?
//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e6+100;vector<LL>node;int n;struct qu
{int op;LL l,r;void input(){scanf("%d%lld%lld",&op,&l,&r);node.push_back(l);node.push_back(r);node.push_back(max(1LL,l-1));node.push_back(max(1LL,r-1));node.push_back(l+1);node.push_back(r+1);}
}q[N];void discreate()
{node.push_back(1);sort(node.begin(),node.end());node.erase(unique(node.begin(),node.end()),node.end());for(int i=1;i<=n;i++){q[i].l=lower_bound(node.begin(),node.end(),q[i].l)-node.begin();q[i].r=lower_bound(node.begin(),node.end(),q[i].r)-node.begin();}
}struct Node
{int l,r,len,sum,lazy1,lazy2;
}tree[N<<2];void pushup(int k)
{tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}void pushdown(int k)
{if(tree[k].lazy1!=-1){tree[k<<1].lazy2=tree[k<<1|1].lazy2=0;int lz=tree[k].lazy1;tree[k].lazy1=-1;tree[k<<1].lazy1=tree[k<<1|1].lazy1=lz;tree[k<<1].sum=tree[k<<1].len*lz;tree[k<<1|1].sum=tree[k<<1|1].len*lz;}if(tree[k].lazy2){int lz=tree[k].lazy2;tree[k].lazy2=0;tree[k<<1].lazy2^=1;tree[k<<1|1].lazy2^=1;tree[k<<1].sum=tree[k<<1].len-tree[k<<1].sum;tree[k<<1|1].sum=tree[k<<1|1].len-tree[k<<1|1].sum;}
}void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;tree[k].len=r-l+1;tree[k].lazy1=-1;tree[k].lazy2=0;tree[k].sum=0;if(l==r)return;int mid=l+r>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}void update(int k,int l,int r,int op)//op=1,2,3
{if(tree[k].l>r||tree[k].r<l)return;if(tree[k].l>=l&&tree[k].r<=r){if(op==1){tree[k].sum=tree[k].len;tree[k].lazy1=1;tree[k].lazy2=0;}else if(op==2){tree[k].sum=0;tree[k].lazy1=0;tree[k].lazy2=0;}else if(op==3){tree[k].sum=tree[k].len-tree[k].sum;tree[k].lazy2^=1;}return;}pushdown(k);update(k<<1,l,r,op);update(k<<1|1,l,r,op);pushup(k);
}int query(int k)
{if(tree[k].l==tree[k].r)return tree[k].l;pushdown(k);if(tree[k<<1].sum!=tree[k<<1].len)return query(k<<1);elsereturn query(k<<1|1);
}int main()
{
#ifndef ONLINE_JUDGE
// freopen("data.in.txt","r",stdin);
// freopen("data.out.txt","w",stdout);
#endif
// ios::sync_with_stdio(false);scanf("%d",&n);for(int i=1;i<=n;i++)q[i].input();discreate();build(1,0,node.size()-1);for(int i=1;i<=n;i++){update(1,q[i].l,q[i].r,q[i].op);printf("%lld\n",node[query(1)]);}return 0;
}
?
總結
以上是生活随笔為你收集整理的CodeForces - 817F MEX Queries(线段树lazy序)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。