• Codeforces J. A Simple Task(多棵线段树)


    题目描述:

    Description

    This task is very simple. Given a string S of length n and q queries each query is on the format i j k which means sort the substring consisting of the characters from i to j in non-decreasing order if k = 1 or in non-increasing order if k = 0.

    Output the final string after applying the queries.

    Input

    The first line will contain two integers n, q (1 ≤ n ≤ 105, 0 ≤ q ≤ 50 000), the length of the string and the number of queries respectively.

    Next line contains a string S itself. It contains only lowercase English letters.

    Next q lines will contain three integers each i, j, k (1 ≤ i ≤ j ≤ n, ).

    Output

    Output one line, the string S after applying the queries.

    Sample Input

    10 5
    abacdabcda
    7 10 0
    5 8 1
    1 4 0
    3 6 0
    7 10 1

     

    10 1
    agjucbvdfk
    1 10 1

    Sample Output

    cbcaaaabdd

    abcdfgjkuv

    思路:

    题目的意思是,给定一个字符串,有q个询问,要把区间[l,r]的字符根据k的值升序(k=1),或降序(k=0)改变。

    因为字母集有26个字母,就可以建立27棵线段树分别维护区间上每个字母出现的次数,一般地,第i棵线段树维护字母i-1+'a'的数目。

    维护字母在区间上出现的次数有什么用?想想我们要做的事情,就是把区间[l,r]上的排一个序,字母集有限,想到计数排序,用一个27大小(0不存)的cnt数组,cnt[i]记录字母i出现的次数

    如果k是1,则下标从1开始,如果对应那一项不为0,说明区间这个位置要被覆盖成i,就直接覆盖掉原来的线段树对应区间[l,r]上记录的字母i出现的次数,注意这里是直接覆盖,而不是累加,所以要修改线段树模板的区间和的upgrade函数的sum[a][r]+=改为sum[a][r]=,(a表示字母a对应的线段树)对应的懒标记也改为=。

    一开始由于循环写的有点长(值代码长度),把计数的变量写叉了,有因为上面没有注意是最直接覆盖,一直出现out of bound错误,一开始还莫名其妙,搞了一个上午一直到晚上才知道写错了(╯‵□′)╯︵┻━┻,bug真好写,改是真难。

    一开始写得麻烦了,比如把区间修改成字母a,然后我还在后面有把在这个区间上的,原来的对应的字母对应的线段树,一个位置一个位置的修改,然后提交,超时。。。

    咋办嘞?原来只要在开始输入l,r那会统计每个字母在这个区间上出现次数后,紧接着立马删掉原来的数据(区间上的数据全置0),这么一改,好家伙,连样例都过不了了-_-||

    找了半天,然后联想到这题的直接覆盖的不同寻常之处,也就是不同于区间和,才发现懒标记我标的有问题,没有懒标记我标0,懒标记为0(区间清零要用的)的还是0,那我在pushdown的时候怎么区分这两种情况呢?

    咋办?标奇偶!神奇,覆盖的标记是1,清零的标记是2,没有标记的是0,这样就可以区分,那我咋使用呢?lz%2就行,1就是1,2就是0,可以正常使用了。

    这题思路清晰,就是要注意细节,果然还是我太菜了。。

    知识点:线段树的覆盖(自编题目)

    代码:(开了氧气上瘾了)(注释依稀可见我超时的地方)

      1 #include <iostream>
      2 #include <cstring>
      3 #include <memory.h>
      4 #define max_n 100005
      5 using namespace std;
      6 char s[max_n];
      7 int sum[27][max_n<<2];
      8 int lz[27][max_n<<2];
      9 int cnt[27];
     10 int n;
     11 int q;
     12 int k;
     13 void pushup(int a,int r)
     14 {
     15     sum[a][r] = sum[a][r<<1]+sum[a][r<<1|1];
     16 }
     17 void build(int a,int r,int lc,int rc)
     18 {
     19     if(lc==rc)
     20     {
     21         if(a==s[lc]-'a'+1)
     22         sum[a][r] = 1;
     23         lz[a][r] = 0;
     24         return;
     25     }
     26     int mid = (lc+rc)>>1;
     27     build(a,r<<1,lc,mid);
     28     build(a,r<<1|1,mid+1,rc);
     29     pushup(a,r);
     30 }
     31 void pushdown(int a,int r,int ln,int rn)
     32 {
     33     if(lz[a][r])
     34     {
     35         //cout << "r" << r << endl;
     36         sum[a][r<<1] = ln*(lz[a][r]%2);//注意这里的改变
     37         sum[a][r<<1|1] = rn*(lz[a][r]%2);//还有这里
     38         lz[a][r<<1] = lz[a][r];
     39         lz[a][r<<1|1] = lz[a][r];
     40         lz[a][r] = 0;
     41     }
     42 }
     43 void upgrade(int a,int r,int L,int R,int lc,int rc,int val)
     44 {
     45     if(L<=lc&&rc<=R)
     46     {
     47         sum[a][r] = (rc-lc+1)*(val%2);//这里,这里!
     48         lz[a][r] = val;//直接覆盖就是等于哦
     49         return;
     50     }
     51     int mid = (lc+rc)>>1;
     52     pushdown(a,r,mid-lc+1,rc-mid);
     53     if(L<=mid) upgrade(a,r<<1,L,R,lc,mid,val);
     54     if(mid<R) upgrade(a,r<<1|1,L,R,mid+1,rc,val);
     55     pushup(a,r);
     56 }
     57 int query(int a,int r,int L,int R,int lc,int rc)
     58 {
     59     if(L<=lc&&rc<=R)
     60     {
     61         return sum[a][r];
     62     }
     63     int mid = (lc+rc)>>1;
     64     pushdown(a,r,mid-lc+1,rc-mid);
     65     int res = 0;
     66     if(L<=mid) res += query(a,r<<1,L,R,lc,mid);
     67     if(mid<R) res += query(a,r<<1|1,L,R,mid+1,rc);
     68     return res;
     69 }
     70 #pragma optimize(2)
     71 int main()
     72 {
     73     cin >> n >> q;
     74     for(int i = 1;i<=n;i++)
     75     {
     76         cin >> s[i];
     77     }
     78     for(int i = 1;i<=26;i++)
     79     {
     80         build(i,1,1,n);
     81     }
     82     int l,r,k;
     83     for(int i=0;i<q;i++)
     84     {
     85         cin >> l >> r >> k;
     86         for(int j = 1;j<=26;j++)
     87         {
     88             cnt[j] = query(j,1,l,r,1,n);
     89             upgrade(j,1,l,r,1,n,2);//直接清零
     90         }
     91         if(k==1)
     92         {
     93             int lp = l;
     94             for(int p = 1; p<=26; p++)
     95             {
     96                 if(cnt[p])
     97                 {
     98                     char ch =p+'a'-1;
     99                     //cout << ch << ":" << cnt[p] << endl;
    100                     upgrade(p,1,lp,lp+cnt[p]-1,1,n,1);
    101                     lp = lp+cnt[p];
    102                     /*for(int j = 0; j<cnt[p];j++)
    103                     {
    104                         upgrade(s[lp]-'a'+1,1,lp,lp,1,n,-1);
    105                         s[lp]=p+'a'-1;
    106                         lp++;
    107                     }*/
    108                 }
    109             }
    110             /*for(int i = 1; i<=n; i++)
    111             {
    112                 cout << s[i];
    113             }
    114             cout << endl;*/
    115         }
    116         else
    117         {
    118             int lp = l;
    119             for(int p = 26; p>=1; p--)
    120             {
    121                 if(cnt[p])
    122                 {
    123                     char ch = p+'a'-1;
    124                     //cout << ch << ":" << cnt[p] << endl;
    125                     upgrade(p,1,lp,lp+cnt[p]-1,1,n,1);
    126                     lp = lp+cnt[p];
    127                     /*for(int j = 0; j<cnt[p];j++)
    128                     {
    129                         upgrade(s[lp]-'a'+1,1,lp,lp,1,n,-1);
    130                         s[lp] = p+'a'-1;
    131                         lp++;
    132                     }*/
    133 
    134                 }
    135             }
    136             /*for(int i = 1; i<=n; i++)
    137             {
    138                 cout << s[i];
    139             }
    140             cout << endl;*/
    141         }
    142     }
    143     for(int i = 1;i<=n;i++)
    144     {
    145         for(int j = 1;j<27;j++)
    146         {
    147             cnt[j] = query(j,1,i,i,1,n);
    148             if(cnt[j])
    149             {
    150                 char ch = j-1+'a';
    151                 cout << ch;
    152             }
    153         }
    154     }
    155     cout << endl;
    156     return 0;
    157 }
  • 相关阅读:
    /dev/null
    useradd
    linux防火墙
    安装ntp服务同步服务器时间
    使用WTM框架项目的部署遇到的问题及解决方式
    .net5 winform 打开文件夹
    maven打包命令
    url.openconnection() 设置超时时间
    java判断http地址是否连通
    解决 curl: (35) Encountered end of file
  • 原文地址:https://www.cnblogs.com/zhanhonhao/p/11247149.html
Copyright © 2020-2023  润新知