zoukankan      html  css  js  c++  java
  • string

    题目描述:

    给定一个由小写字母组成的字符串$s$。

    有$m$次操作,每次操作给定$3$个参数$l,r,x$。

    如果$x$ $=$ $1$,将$s[l]$ $~$ $s[r]$升序排序;

    如果$x$ $=$ $0$,将$s[l]$ $~$ $s[r]$降序排序。

    你需要求出最终序列。

    输入格式:

    第一行两个整数$n,m$。

    第二行一个字符串$s$。

    接下来$m$行每行三个整数$x,l,r$。

    输出格式:

    一行一个字符串表示答案。

    输入样例:

    5 2
    cabcd
    1 3 1
    3 5 0
    

    输出样例:

    abdcc

    数据范围:

    对于$100\%$的数据,$n,m$ $≤$ $100000$。




    思路:

    因为数据达到了$1e5$,所以考虑$m$ $log$ $n$的复杂度(可能有常数)。

    观察到字符串只由小写字母组成,所以考虑一种类似于桶排的思想。

    首先考虑一个$01$序列,如果将它排序只需要考虑$0$的数量和$1$的数量即可。

    如果把字符串看成一个由$1$ $~$ $26$构成的序列,并现将$1$看作$0$,其余看作$1$,将这个字符串排序就会变成一个前面是$0$,后面是$1$的序列,因为是把$1$转化成$0$的,所以序列中的$0$就是$1$;再将$1$和$2$看作$0$,其余看作$1$,再排序就会变成一个前面是$0$,后面是$1$的序列,因为$1$的位置已经确定了,所以剩下的$0$的位置就是$2$了;以此类推。

    考虑用线段树维护这个$01$区间中$0$和$1$的数量,依次为$1,1、2,1、2、3,1、2、3、4……$做线段树,然后如上记录答案。

    代码

     1 #include <bits/stdc++.h>
     2 #define INF 0x3f3f3f3f
     3 using namespace std;
     4 int n, m, q[100010], sum[100010], l[100010], r[100010], x[100010], ans[100010];
     5 char s[100010];
     6 struct Tree {int l, r, val, lazy;}tree[800010];
     7 void build(int u, int l, int r)
     8 {
     9     int mid = (l + r) >> 1;
    10     tree[u].l = l, tree[u].r = r, tree[u].lazy = -1;
    11     if(l == r) {tree[u].val = sum[l]; return;}
    12     build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
    13     tree[u].val = tree[u << 1].val + tree[u << 1 | 1].val;
    14     return;
    15 }
    16 void pushdown(int u)
    17 {
    18     if(!(~tree[u].lazy)) return;
    19     int mid = (tree[u].l + tree[u].r) >> 1;
    20     tree[u << 1].lazy = tree[u << 1 | 1].lazy = tree[u].lazy;
    21     tree[u << 1].val = tree[u << 1].lazy * (mid - tree[u].l + 1), tree[u << 1 | 1].val = tree[u << 1 | 1].lazy * (tree[u].r - mid);
    22     tree[u].lazy = -1;
    23     return;
    24 }
    25 void change(int u, int l, int r, int x)
    26 {
    27     if(tree[u].l > r || tree[u].r < l) return;
    28     if(tree[u].l >= l && tree[u].r <= r) {tree[u].lazy = x, tree[u].val = x * (tree[u].r - tree[u].l + 1); return;}
    29     pushdown(u);
    30     change(u << 1, l, r, x), change(u << 1 | 1, l, r, x);
    31     tree[u].val = tree[u << 1].val + tree[u << 1 | 1].val;
    32     return;
    33 }
    34 int query(int u, int l, int r)
    35 {
    36     if(tree[u].l > r || tree[u].r < l) return 0;
    37     if(tree[u].l >= l && tree[u].r <= r) return tree[u].val;
    38     pushdown(u);
    39     return query(u << 1, l, r) + query(u << 1 | 1, l, r);
    40 }
    41 void solve(int num)
    42 {
    43     for(int i = 1; i <= n; ++i) sum[i] = (q[i] > num ? 1 : 0);
    44     build(1, 1, n);
    45     for(int i = 1; i <= m; ++i)
    46     {
    47         int cnt = query(1, l[i], r[i]);
    48         if(x[i] == 1) change(1, l[i], r[i] - cnt, 0), change(1, r[i] - cnt + 1, r[i], 1);
    49         else change(1, l[i], l[i] + cnt - 1, 1), change(1, l[i] + cnt, r[i], 0);
    50     }
    51     for(int i = 1; i <= n; ++i)
    52     {
    53         int cnt = query(1, i, i);
    54         if(ans[i]) continue;
    55         if(!cnt) ans[i] = num;
    56     }
    57     return;
    58 }
    59 int main()
    60 {
    61     scanf("%d %d %s", &n, &m, s + 1);
    62     for(int i = 1; i <= n; ++i) q[i] = (int)s[i] - 'a' + 1;
    63     for(int i = 1; i <= m; ++i) scanf("%d %d %d", &l[i], &r[i], &x[i]);
    64     for(int i = 1; i <= 26; ++i) solve(i);
    65     for(int i = 1; i <= n; ++i) printf("%c", (char)(ans[i] + 'a' - 1));
    66     return 0;
    67 }
  • 相关阅读:
    Yarn下分片和分块源代码分析
    Yarn下Map数控制
    hadoop中使用的Unsafe.java
    hbase的coprocessor使用(转)
    eclipse插件
    短线及时发现个股机会的七大招数
    hadoop分类输出
    安装ubuntu-tweak
    rabbitmq安装使用
    “-Xmx1024m -Xms1024m -Xmn512m -Xss256k”——Java运行参数(转)
  • 原文地址:https://www.cnblogs.com/qqq1112/p/13582431.html
Copyright © 2011-2022 走看看