zoukankan      html  css  js  c++  java
  • C.冬幕节闹剧 (线段树+离散化)(中国地质大学第十四届ACM华中地区邀请赛19.5.18) 解题报告 Apare

    C.冬幕节闹剧(中国地质大学第十四届ACM华中地区邀请赛19.5.18) 解题报告

    xzc ccnu 2019.5.20


      这题现场就两个AC的,一个是武大的神仙队,还有一个就是我校的zyf。


    题意:

      巫妖王训练军队。他想让某些区间的人戴帽子,某些不戴帽。军队有n个人,他要进行q个操作。(1<=n<=1000,000,000, 1<=1<=50,000) 每个操作为L R op

    • L R表示操作的闭区间
    • op = 1 表示这个区间的人全部不戴帽子
    • op = 2 表示这个区间的人全部要戴帽子
    • op = 3 表示这个区间的人全部状态反转(戴帽子的脱下,没戴帽子的带上)
    • op = 4 表示询问这个区间内戴帽子的人数量

    输入格式

    n q
    L1 R1 op1
    L2 R2 op2

    Lq Rq opq


    Sample

    Sample input

    3 6 
    1 1 1 
    1 1 4
    1 2 2 
    1 2 4
    1 3 3 
    1 3 4
    

    Sample output

    0
    1
    2
    

    还有一个zyf给我的样例
    input

    10000 5
    1 5000 2
    1 2500 1
    1 5000 4
    1 10000 3
    1 10000 4
    

    output

    2500
    2500
    

    思路:

    • 显然是线段树
    • n很大,要离散化

    我的做法

    1. 如果不考虑离散化,我们先考虑线段树维护的是什么
      线段树维护区间的状态flag。我们可以转化为染色问题。
    • flag为0代表这个区间[left,right]所有的士兵都没戴帽子,
    • flag为1代表这个区间所有士兵都带了帽子
    • flag为-1代表不统一
    1. 然后我们考虑离散化的问题:
    • 因为线段树维护的是一段区间,而我们离散化后的都是离散的点。所以我们需要进行一些处理
      先看一组样例吧

    设所有操作设计的区间有3个:[3,8],[15,16],[16,30]
    我们将所有的Ri+1也一同离散化
    先看一个表格

    序号 1 2 3 4 5 6 7 8
    端点(数组a ) 3 8 9 15 16 17 30 31
    线段表示的范围 [3,7] [8,8] [9,14] [15,15] [16,16] [17,29] [30,30]
    线段树的叶子节点 [1,1] [2,2] [3,3] [4,4] [5,5] [6,6] [7,7]

      从这个表,我们可以很清楚的看到,线段树维护的其实是一个坐闭右开的区间。所以我们需要把Ri+1一起离散化,然后就可以多出一个[Ri,Ri]的闭区间。
      每个区间[left,right]维护的范围正好是[a[left],a[right+1]]
      这样的话,我们就可以像不离散化一样维护线段树了

    关于线段树的部分

    • 对于update操作(1和2),如果要更新的区间[uL,uR]和线段树当前节点表示的区间[left,right]重合,j就直接把区间标记flag[pos]改掉;否则pushdown()递归向下更新,然后pushup()
    • 对于reverse操作(3),如果重合且区间状态一样,就直接flag[pos]^=1,return;否则向下递归
    • 对于查询,同更新,不用pushup
    • 有些暴力,但是没有被卡掉(145ms)
    • zyf写的是lazy[]和sum[],维护的是区间和,这样不会被卡
    • 具体见代码

    我的代码:

    /**************************************************************
        Problem: 2181
        User: apare
        Language: C++
        Result: 正确
        Time:172 ms
        Memory:6884 kb
    ****************************************************************/
    #include <bits/stdc++.h>
    #define For(i,a,b) for(register int i=(a);i<=(b);++i)
    #define Rep(i,a,b) for(register int i=(a);i>=(b);--i)
    #define Mst(a,b) memset(a,(b),sizeof(a))
    #define LL long long
    #define MP make_pair
    #define pb push_back
    using namespace std;
    const int maxn = 2e5+30;
    const int maxq = 5e4+20;
    //向zyf看齐 
    int flag[maxn<<2]; //0都没有,1都有,-1杂色 
    int cnt;
    int qL[maxq],qR[maxq];
    int a[maxn];
    struct Node{
        int L,R,op;
        void input()
        {
            scanf("%d%d%d",&L,&R,&op);
            a[++cnt] = L;
            a[++cnt] = R;
            a[++cnt] = R+1;
        }
    }node[maxq]; 
    void build(int left,int right,int pos=1);
    void push_down(int pos);
    void push_up(int pos);
    void update(int left,int right,int uL,int uR,int op,int pos);
    void Reverse(int left,int right,int uL,int uR,int pos);
    int query(int left,int right,int qL,int qR,int pos);
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int n,q;
        while(scanf("%d%d",&n,&q)!=EOF)
        {
            cnt = 0;
            For(i,1,q)
            {
                node[i].input();
            }
            sort(a+1,a+1+cnt);
            cnt = unique(a+1,a+cnt+1)-a-1;
            cnt--;
            For(i,1,q)
            {
                qL[i] = lower_bound(a+1,a+cnt+1,node[i].L)-a;
                qR[i] = lower_bound(a+1,a+cnt+1,node[i].R)-a;
            }
            build(1,cnt);
            For(i,1,q)
            {
                switch (node[i].op)
                {
                    case 1: update(1,cnt,qL[i],qR[i],0,1);break;
                    case 2: update(1,cnt,qL[i],qR[i],1,1);break;
                    case 3: Reverse(1,cnt,qL[i],qR[i],1);break;
                    case 4: printf("%d
    ",query(1,cnt,qL[i],qR[i],1));break;
                }
            }
        }  
        return 0;
    }
    void build(int left,int right,int pos)
    {
        if(left==right)
        {
            flag[pos] = 0;
            return;
        }
        int mid = (left+right)>>1;
        build(left,mid,pos<<1);
        build(mid+1,right,pos<<1|1);
    } 
    void push_down(int pos)
    {
        if(flag[pos]!=-1) 
            flag[pos<<1] = flag[pos<<1|1] = flag[pos]; 
    }
    void push_up(int pos)
    {
        flag[pos] = (flag[pos<<1]==flag[pos<<1|1])?flag[pos<<1]:-1;
    }
    void update(int left,int right,int uL,int uR,int op,int pos)
    {
        if(left==uL&&right==uR)
        {
            flag[pos] = op;
            return;     
        } 
        push_down(pos);
        int mid = (left+right)>>1;
        if(uL>mid) 
            update(mid+1,right,uL,uR,op,pos<<1|1);
        else if(uR<=mid) 
            update(left,   mid,uL,uR,op,pos<<1);
        else
            update( left,  mid,   uL,mid,op,pos<<1),
            update(mid+1,right,mid+1, uR,op,pos<<1|1);
        push_up(pos);
         
    }
    void Reverse(int left,int right,int uL,int uR,int pos)
    {
        if(left==uL&&right==uR&&flag[pos]!=-1)
        {
            flag[pos]^=1;
            return;
        }
        push_down(pos);
        int mid = (left+right)>>1;
        if(uL>mid) 
            Reverse(mid+1,right,uL,uR,pos<<1|1);
        else if(uR<=mid) 
            Reverse(left,   mid,uL,uR,pos<<1);
        else
            Reverse( left,  mid,   uL,mid,pos<<1),
            Reverse(mid+1,right,mid+1, uR,pos<<1|1);
        push_up(pos);
    }
    int query(int left,int right,int qL,int qR,int pos)
    {
        if(left==qL&&qR==right&&flag[pos]!=-1)
        { 
            return flag[pos]?a[right+1]-a[left]:0;
        }
        push_down(pos);
        int mid = (left+right)>>1;
        if(qL>mid) 
            return query(mid+1,right,qL,qR,pos<<1|1);
        else if(qR<=mid) 
            return query(left,   mid,qL,qR,pos<<1);
        else
            return query( left,  mid,   qL,mid,pos<<1)
            +      query(mid+1,right,mid+1, qR,pos<<1|1);
    }
    
    

  • 相关阅读:
    MongoDB小结07
    MongoDB小结07
    MongoDB小结06
    MongoDB小结05
    MongoDB小结04
    MongoDB小结03
    MongoDB小结02
    MongoDB小结01
    this与super
    UVa 11174
  • 原文地址:https://www.cnblogs.com/Apare-xzc/p/12243644.html
Copyright © 2011-2022 走看看