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;
}

 

posted @ 2020-04-21 22:13  L·S·D  阅读(190)  评论(0编辑  收藏  举报