codeforces-915E.-Physical Education Lessons
codeforces-915E.-Physical Education Lessons
传送门:https://codeforces.com/contest/915/problem/E
题意:
有n天工作日1-n,q个指令
每个指令有三个参数 l,r,k
如果 k=1,那么从 l到 r (包含端点)的所有日子都变成非工作日。
如果 k=2,那么从 l 到 r(包含端点)的所有日子都变成工作日。
统计每个指令下发后,剩余的工作日天数。
目测 线段树裸题 但在洛谷上看到有大佬们用平衡树 ,珂朵莉树 ,动态开点等等等神奇算法,但我还都 没有学,感兴趣的可以去看看 https://www.luogu.com.cn/problemnew/solution/CF915E
但是数据范围很大 1<=n<=1e9 1<=q<=3e5
可以发现 我们建不出4e9的数组
但是能开的出4*2*3e5的(只存每段区间的两个坐标,因为是两个坐标,要再开大一倍,不然会wa17),离线解决这个问题
所以要加一个离散化
我用的是vector 排序 去重 再用二分查询 用map和unorder_map应该会tle
可能我太菜了吧 零零散散连玩带改改了小半天
先把数据读入放入vector 离散化,注意在存左右坐标的时候把r++,这样 l==r 时 能把那个距离抻出来,不然的话,这个距离就没了
然后还要记一个ans为1~n中没有被ve[0]~ve[ve.size()-1] 覆盖到的值,这样的值就是1,没有被改变过
然后就是一个区间更新的线段树
#include <bits/stdc++.h> using namespace std; #define ll long long #define lowbit(a) ((a)&-(a)) #define clean(a,b) memset(a,b,sizeof(a)) const int mod = 1e9 + 7; const int inf=0x3f3f3f3f; const int maxn = 3e5+10; inline int read(){char c=getchar();int tot=1;while ((c<'0'|| c>'9')&&c!='-') c=getchar();if (c=='-'){tot=-1;c=getchar();} int sum=0;while (c>='0'&&c<='9'){sum=sum*10+c-'0';c=getchar();}return sum*tot;} int _; vector<int>ve; int getid(int x){return lower_bound(ve.begin(),ve.end(),x)-ve.begin()+1;} ////////////////////////////////////////////////////////////////////////// struct node { int l,r,sum,add,vis; }tree[maxn*8]; struct node1 { int l,r,k; }q[maxn]; int cnt; void push_down(int root) { if(tree[root].add==1)//1 { tree[root<<1].sum=ve[tree[root<<1].r]-ve[tree[root<<1].l-1]; tree[root<<1|1].sum=ve[tree[root<<1|1].r]-ve[tree[root<<1|1].l-1]; tree[root<<1].vis=1; tree[root<<1|1].vis=1; tree[root<<1].add=1; tree[root<<1|1].add=1; } else //0 { tree[root<<1].sum=0; tree[root<<1|1].sum=0; tree[root<<1].vis=1; tree[root<<1|1].vis=1; tree[root<<1].add=0; tree[root<<1|1].add=0; } tree[root].vis=0; tree[root].add=0; } void build(int l,int r,int root) { tree[root].l=l; tree[root].r=r; if(l==r) { tree[root].sum=ve[l]-ve[l-1]; return ; } int mid=(l+r)>>1; build(l,mid,root<<1); build(mid+1,r,root<<1|1); tree[root].sum=tree[root<<1|1].sum+tree[root<<1].sum; } void update(int l,int r,int k,int root) { if(tree[root].l==l&&tree[root].r==r) { if(k==1) tree[root].sum=0,tree[root].add=0; else if(k==2) tree[root].sum=ve[r]-ve[l-1],tree[root].add=1; tree[root].vis=1; return ; } if(tree[root].vis) push_down(root); int mid=(tree[root].l+tree[root].r)>>1; if(r<=mid) update(l,r,k,root<<1); else if(l>mid) update(l,r,k,root<<1|1); else { update(l,mid,k,root<<1); update(mid+1,r,k,root<<1|1); } tree[root].sum=tree[root<<1].sum+tree[root<<1|1].sum; } ////////////////////////////////////////////////////////////////////////// int main() { // freopen("in.in","r",stdin); int n=read(); int m=read(); int l,r,k; for(int i=1;i<=m;i++) { q[i].l=read(),q[i].r=read(),q[i].k=read(); q[i].r++; ve.push_back(q[i].l); ve.push_back(q[i].r); } sort(ve.begin(),ve.end()); ve.erase(unique(ve.begin(),ve.end()),ve.end()); int ans=ve[0]-1+n-ve[ve.size()-1]+1; build(1,ve.size()-1,1); for(int i=1;i<=m;i++) { update(getid(q[i].l),getid(q[i].r)-1,q[i].k,1); printf("%d\n",tree[1].sum+ans); } return 0; }