(线段树区间赋值)CSU 1942 - Sort String

Posted tak_fate

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(线段树区间赋值)CSU 1942 - Sort String相关的知识,希望对你有一定的参考价值。

题意:

一个串(串中只有26个小写字母),选一个区间进行排序,进行100000次,输出最后的串。

 

分析:

比赛的时候很懵逼,感觉这题跟之前的额大崩龙有点像,但是没多想,也怪自己太菜了。

确实是真的像,甚至是一模一样啊。

对于每次排序只需要进行一次类似计数排序的的操作即可,26个字符,进行26次区间赋值即可。理论上时间能过得去。

 

代码:

  1 #include <queue>
  2 #include <string>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <map>
  8 
  9 
 10 using namespace     std;
 11 
 12 typedef long long ll;
 13 typedef unsigned long long ull;
 14 typedef pair<int, int> pii;
 15 typedef pair<ull, ull> puu;
 16 
 17 #define inf (0x3f3f3f3f)
 18 #define lnf (0x3f3f3f3f3f3f3f3f)
 19 #define eps (1e-8)
 20 #define fi first
 21 #define se second
 22 
 23 //--------------------------
 24 
 25 const ll mod = 1000000007;
 26 const int maxn = 100010;
 27 
 28 
 29 char str[maxn];
 30 int n;
 31 int q;
 32 
 33 struct Node {
 34     int left, right;
 35     int num[26];
 36     int lazy;
 37 } node[maxn << 2];
 38 
 39 void push_up(int n) {
 40     for(int i = 0; i < 26; i++) {
 41         node[n].num[i] = node[n << 1].num[i] + node[n << 1 | 1].num[i];
 42     }
 43 }
 44 
 45 void push_down(int n) {
 46     if(node[n].lazy != -1) {
 47         node[n << 1].lazy = node[n << 1 | 1].lazy = node[n].lazy;
 48         memset(node[n << 1].num, 0, sizeof(node[n << 1].num));
 49         memset(node[n << 1 | 1].num, 0, sizeof(node[n << 1 | 1].num));
 50         node[n << 1].num[node[n].lazy] = (node[n].right - node[n].left + 1) - (node[n].right - node[n].left + 1) / 2;
 51         node[n << 1 | 1].num[node[n].lazy] = (node[n].right - node[n].left + 1) / 2;
 52         node[n].lazy = -1;
 53     }
 54 }
 55 
 56 void update(int n, int left, int right, char val) {
 57     if(node[n].left >= left && node[n].right <= right) {
 58         node[n].lazy = val - a;
 59         memset(node[n].num, 0, sizeof(node[n].num));
 60         node[n].num[node[n].lazy] = node[n].right - node[n].left + 1;
 61         return ;
 62     }
 63     push_down(n);
 64     int mid = (node[n].left + node[n].right) >> 1;
 65     if(mid >= left)update(n << 1, left, right, val);
 66     if(mid < right)update(n << 1 | 1, left, right, val);
 67     push_up(n);
 68 }
 69 
 70 int query(int n, int left, int right, char val) {
 71     if(node[n].left >= left && node[n].right <= right) {
 72         return node[n].num[val - a];
 73     }
 74     push_down(n);
 75     int mid = (node[n].left + node[n].right) >> 1;
 76     int sum = 0;
 77     if(mid >= left)sum += query(n << 1, left, right, val);
 78     if(mid < right)sum += query(n << 1 | 1, left, right, val);
 79     return sum;
 80 }
 81 
 82 
 83 void build(int n, int left, int right) {
 84     node[n].left = left;
 85     node[n].right = right;
 86     node[n].lazy = -1;
 87     if(left == right) {
 88         node[n].num[str[left] - a] = 1;
 89         return ;
 90     }
 91     int mid = (left + right) >> 1;
 92     build(n << 1, left, mid);
 93     build(n << 1 | 1, mid + 1, right);
 94     push_up(n);
 95 }
 96 
 97 void print(int n) {
 98     if(node[n].left == node[n].right) {
 99         for(int i = 0; i < 26; i++) {
100             if(node[n].num[i] != 0) {
101                 printf("%c", i + a);
102                 break;
103             }
104         }
105         return ;
106     }
107     push_down(n);
108     print(n << 1);
109     print(n << 1 | 1);
110 }
111 
112 void solve() {
113     while(~scanf("%d%d", &n, &q)) {
114         memset(node, 0, sizeof(node));
115         scanf("%s", str + 1);
116         build(1, 1, n);
117         while(q--) {
118             int l, r, op;
119             scanf("%d%d%d", &l, &r, &op);
120             int num[26] = {0};
121             for(int i = 0; i < 26; i++) {
122                 num[i] = query(1, l, r, i + a);
123             }
124             if(op == 1) {
125                 for(int i = 0; i < 26; i++) {
126                     if(num[i] > 0) {
127                         update(1, l, l + num[i] - 1, i + a);
128                         l += num[i];
129                     }
130                 }
131             } else {
132                 for(int i = 25; i >= 0; i--) {
133                     if(num[i] > 0) {
134                         update(1, l, l + num[i] - 1, i + a);
135                         l += num[i];
136                     }
137                 }
138             }
139         }
140         print(1);
141         puts("");
142     }
143 
144 
145 
146 }
147 
148 int main() {
149 #ifndef ONLINE_JUDGE
150     freopen("1.in", "r", stdin);
151     freopen("1.out", "w", stdout);
152 #endif
153     solve();
154     return 0;
155 }

 

以上是关于(线段树区间赋值)CSU 1942 - Sort String的主要内容,如果未能解决你的问题,请参考以下文章

Tyvj 1518 CPU监控——极恶线段树

CSU - 1542 Flipping Parentheses (线段树)

csu 1809 Parenthesis(线段树)

湖南省第十二届大学生计算机程序设计竞赛---Parenthesis(线段树求区间最值)

线段树

HDU 3397 Sequence operation 多标记线段树