CF817F MEX Queries(线段树上二分)

题意

维护一个01串,一开始全部都是0

3种操作

1.把一个区间都变为1

2.把一个区间都变为0

3.把一个区间的所有数字翻转过来

每次操作完成之后询问区间最小的0的位置

l,r<=10^18

题解

区间操作想到线段树,离散化不用说,l,r太大了。

1,2,3操作非常好维护。

然后在查询中二分查询就好了。

一开始看别的博客(对,我看题解了,太菜)说要加1节点和r+1节点不知道为什么。

因为我的查询想的是,查询前面全都是1的区间的长度。后来发现做不了。就乖乖照题解做了。

  1 #include<iostream>
  2 #include<cstring>
  3 #include<cstdio>
  4 #include<cmath>
  5 #include<algorithm>
  6 #include<map>
  7 using namespace std;
  8 const long long N=150020;
  9 map<long long,long long> mp;
 10 long long b[N*4],n,m,cnt;
 11 struct ask{
 12     long long l,r;
 13     long long k;
 14 }q[N];
 15 struct tree{
 16     long long l,r,sum,sev,lazy;
 17 }tr[N*40];
 18 void build(long long l,long long r,long long now){
 19     tr[now].l=l;
 20     tr[now].r=r;
 21     tr[now].lazy=-1;
 22     if(l==r)return;
 23     long long mid=(l+r)>>1;
 24     build(l,mid,now*2);
 25     build(mid+1,r,now*2+1);
 26 }
 27 void pushdown(long long now){
 28     long long mid=(tr[now].l+tr[now].r)>>1;
 29     if(tr[now].lazy!=-1){
 30         tr[now*2].lazy=tr[now*2+1].lazy=tr[now].lazy;
 31         tr[now*2].sum=(mid-tr[now].l+1)*tr[now].lazy;
 32         tr[now*2+1].sum=(tr[now].r-mid)*tr[now].lazy;
 33         tr[now*2].sev=tr[now*2+1].sev=0;
 34         tr[now].lazy=-1;
 35     }
 36     if(tr[now].sev){
 37         tr[now*2].sev^=1;
 38         tr[now*2+1].sev^=1;
 39         tr[now*2].sum=(mid-tr[now].l+1)-tr[now*2].sum;
 40         tr[now*2+1].sum=(tr[now].r-mid)-tr[now*2+1].sum;
 41         tr[now].sev=0;
 42     }
 43 }
 44 void update(long long l,long long r,long long now,long long k){
 45 //    cout<<l<<" "<<r<<" "<<tr[now].l<<" "<<tr[now].r<<" "<<now<<endl;
 46     pushdown(now);
 47     if(tr[now].l==l&&tr[now].r==r){
 48         tr[now].sum=(tr[now].r-tr[now].l+1)*k;
 49         tr[now].lazy=k;
 50         tr[now].sev=0;
 51         return ;
 52     }
 53     long long mid=(tr[now].l+tr[now].r)>>1;
 54     if(l>mid){
 55         update(l,r,now*2+1,k);
 56     }
 57     else if(r<=mid){
 58         update(l,r,now*2,k);
 59     }
 60     else{
 61         update(l,mid,now*2,k);
 62         update(mid+1,r,now*2+1,k);
 63     }
 64     tr[now].sum=tr[now*2].sum+tr[now*2+1].sum;
 65 }
 66 void serve(long long l,long long r,long long now){
 67     pushdown(now);
 68     if(tr[now].l==l&&tr[now].r==r){
 69         tr[now].sum=(tr[now].r-tr[now].l+1)-tr[now].sum;
 70         tr[now].sev^=1;
 71         return;
 72     }
 73     long long mid=(tr[now].l+tr[now].r)>>1;
 74     if(l>mid)serve(l,r,now*2+1);
 75     else if(r<=mid)serve(l,r,now*2);
 76     else{
 77         serve(l,mid,now*2);
 78         serve(mid+1,r,now*2+1);
 79     }
 80     tr[now].sum=tr[now*2].sum+tr[now*2+1].sum;
 81 }
 82 void check(long long now){
 83     if(tr[now].l==tr[now].r){
 84         printf("%lld\n",b[tr[now].l]);
 85         return ;
 86     }
 87     long long mid=(tr[now].l+tr[now].r)>>1;
 88     pushdown(now);
 89     if(tr[now*2].sum<mid-tr[now].l+1)check(now*2);
 90     else return check(now*2+1);
 91 }
 92 int main(){
 93     scanf("%lld",&m);
 94     for(long long i=1;i<=m;i++){
 95         scanf("%lld%lld%lld",&q[i].k,&q[i].l,&q[i].r);
 96         q[i].r++;
 97         b[++cnt]=q[i].l;
 98         b[++cnt]=q[i].r;
 99     }
100     b[++cnt]=1;
101     sort(b+1,b+1+cnt);
102     n=unique(b+1,b+1+cnt)-(b+1);
103     for(long long i=1;i<=n;i++){
104         mp[b[i]]=i;
105     }
106     build(1,n,1);
107     for(long long i=1;i<=m;i++){
108         if(q[i].k==1){
109             update(mp[q[i].l],mp[q[i].r]-1,1,1);
110         }
111         else if(q[i].k==2){
112             update(mp[q[i].l],mp[q[i].r]-1,1,0);
113         }
114         else{
115             serve(mp[q[i].l],mp[q[i].r]-1,1);
116         }
117         check(1);
118     }
119     return 0;
120 }

原文地址:https://www.cnblogs.com/Xu-daxia/p/9397803.html

时间: 2024-11-06 01:52:44

CF817F MEX Queries(线段树上二分)的相关文章

CF1083C Max Mex(线段树上二分)

这题卡倍增害我T了一发= = 显然Mex是可以二分的,于是就可以考虑二分一个Mex然后check一下 然后怎么check呢?可以对点权建一棵线段树,节点\([l,r]\)表示,链上点权的集合包括\([l,r]\)时,最短的链的端点 合并两个区间就是在四个端点间选两个作为新链的端点,判断另外两个端点在不在这条链上,在的话这就是一条合法的链.判断方法就是判断一下两段的距离是否等于一整条链的距离. 这样时间复杂度是\(O(nlog^2n)\),感觉可过的样子?然而还可以在线段树上二分把时间复杂度优化到

【BZOJ】4293: [PA2015]Siano 线段树上二分

[题意]给定n棵高度初始为0的草,每天每棵草会长高a[i],m次收割,每次在d[i]天将所有>b[i]的草收割到b[i],求每次收割量.n<=500000. [算法]线段树上二分 [题解]按照生长速度a[]排序后,容易发现数列永远单调. 在线段树上的区间维护以下值: 1.最后一棵草的高度a 2.上次收割日期b 3.总的草高和c 4.总的生长速度和d 5.收割标记D和B 上传的时候注意右区间收割晚于左区间时强制合并. 下传的时候注意标记D和B直接覆盖. 线段树上二分: 1.判断当前区间是否符合(

UVALive - 8086 Substring Sorting (后缀数组+线段树上二分)

题意: 给一个串S, 多次询问k和m,求S的所有长度为k的不同子串中,字典序为排第m的串的最早出现位置 简化问题: 如果没有长度k的限制,并且没有不同子串的限制要怎么做.要字典序第m大,容易想到用后缀数组,因为它就是将n个后缀按字典序排好的,设f(i) = 排名<=i的所有后缀的所有前缀的个数和,假设答案的串是排名i的后缀的前缀,那么有f(i) >= k 且 f(i-1) < k,则满足二分性,可以二分后缀排名解决. 扩展: 有不同子串的限制,则类似求一个串有多少不同子串那样,对于每个排

CF817F MEX Queries

题意 维护一个\(01\)串,一开始全部都是\(0\) \(3\)种操作 \(1.\)把一个区间都变为\(1\) \(2.\)把一个区间都变为\(0\) \(3.\)把一个区间的所有数字翻转过来 每次操作完成之后询问区间最小的\(0\)的位置 \(l,r<=10^{18}\) Sol 直接上线段树,如果这个区间左边是满的就去右边,否则去左边 动态开点,加上\(lazy\) 但这样会爆空间 所以把区间离散化 注意要离散\(1\),\(l\),\(r\),\(l+1\),\(r+1\) 这些都可能会

Blog Post Rating CodeForces - 806E (线段树二分)

题目链接 题目大意: 有一个博客, 初始分数为$0$, 有$n$个人, 第$i$个人有一个期望值$a_i$, 如果第$i$个人浏览博客时,博客赞数高于$a_i$博客分数$-1$, 低于$+1$, 相等不变, 对于每个$i$, 求出$[1,i]$的人按任意顺序浏览博客后最大分数. 题解: 首先, 用贪心可以知道所有人按期望升序排列, 最后得分一定最大 由于期望有负数, 博客分数一定是先减后增的, 然后对这两段分类讨论 对于递减的段, 最后分数为递增递减的临界值 假设临界值为$x$, 设比$x$小的

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

BZOJ3932(主席树上二分+差分

按时间作为主席树的版本,每个版本的主席树都是一个权值线段树. 差分消去时间影响 对于当前时间版本的主席树查询前K大即可. 树上二分时结束后切记判定l==r的状态(易错 l==r叶子节点可能存在多个值(值大小为sum/siz ) 用I64dOLE了好久 .. .... . .. . . . . . . . .. . 用bit/stdc++.h  CE..... #include<cmath> #include<cstdio> #include<cstring> #incl

Codeforces 817F - MEX Queries

817F - MEX Queries 思路: 离线+离散化+线段树 代码: #include<bits/stdc++.h> using namespace std; #define LL long long #define pb push_back #define ls rt<<1,l,m #define rs rt<<1|1,m+1,r const int N=1e5+5; int t[N],tree[N*16],lazy[N*16]; LL l[N],r[N]; v