~~~题面~~~

题解:

  观察到字母只有26个,因此考虑对这26个字母分别维护,每个线段树维护一个字母,如果一个线段树的某个叶节点有值,表示当前叶节点所在位置的字母是现在这个线段树代表的字母。

  那么对于每一个操作,我们已经知道最后排好序之后肯定是按aaaabbbbccccddd……这样的序列排下去的(有些字母可能没有),每个字母都集中在自己的区间内。

  那么我们只需要知道每个字母之前的字母有多少个,就可以知道这个字母所在区间,因此按顺序修改。

  (以下操作均视为在每个字母对应的线段树上操作)先查询a的个数,并把当前修改的区间内赋0,然后把前1~tot_a全都赋1,表示这段区间是属于a的(全都放上1)。

  记在统计当前字母之前找到的字母个数之和为tot,则每次都是把当前线段树管理的字母全都移动到tot + 1~tot + 字母个数,相当于跟修改a类似的区间操作。只不过属于这个字母的区间的开始端点是tot + 1(其实a的情况也可以视作是tot + 1,因为这个时候tot = 0)

 #include<bits/stdc++.h>
using namespace std;
#define R register int
#define LL long long
#define AC 101000
#define ac 401000 int n, m, id, tot, add, t;
int l[ac], r[ac];
char s[AC], ans[AC]; int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c -'', c = getchar();
return x;
} inline void upmin(int &a, int b)
{
if(b < a) a = b;
} inline void upmax(int &a, int b)
{
if(b > a) a = b;
} struct segament_tree{
int tree[ac], lazy[ac], id; inline void init()
{
memset(lazy, -, sizeof(lazy));
} inline void update(int x)
{
tree[x] = tree[x * ] + tree[x * + ];
} inline void pushdown(int x)
{
if(lazy[x] != -)
{
int ll = x * , rr = ll + ;
lazy[ll] = lazy[rr] = lazy[x];
if(!lazy[x]) tree[ll] = tree[rr] = ;
else
{
int mid = (l[x] + r[x]) >> ;
tree[ll] = mid - l[ll] + ;
tree[rr] = r[rr] - mid;
}
lazy[x] = -;
}
} void build(int x, int ll, int rr)
{
if(!id) l[x] = ll, r[x] = rr;
if(ll == rr)
{
if(s[ll] == id + 'a') tree[x] = ;
return ;
}
int mid = (ll + rr) >> ;
build(x * , ll, mid);
build(x * + , mid + , rr);
update(x);
} void find(int x, int ll, int rr)
{
if(!tree[x]) return ;
if(l[x] == ll && r[x] == rr){add += tree[x]; return ;}
pushdown(x);
int mid = (l[x] + r[x]) >> ;
if(rr <= mid) find(x * , ll, rr);
else if(ll > mid) find(x * + , ll, rr);
else
{
find(x * , ll, mid);
find(x * + , mid + , rr);
}
update(x);
} void change(int x, int ll, int rr)
{
if(l[x] == ll && r[x] == rr)
{
lazy[x] = t;
if(t) tree[x] = rr - ll + ;
else tree[x] = ;
return ;
}
pushdown(x);
int mid = (l[x] + r[x]) >> ;
if(rr <= mid) change(x * , ll, rr);
else if(ll > mid) change(x * + , ll, rr);
else
{
change(x * , ll, mid);
change(x * + , mid + , rr);
}
update(x);
} void get(int x)
{
if(!tree[x]) return ;
if(tree[x] == r[x] - l[x] + )
{
for(R i = l[x]; i <= r[x]; i ++) ans[i] = id + 'a';
return ;
}
pushdown(x);
if(tree[x * ]) get(x * );
if(tree[x * + ]) get(x * + );
} }T[]; void pre()
{
n = read(), m = read();
scanf("%s", s + );
for(R i = ; i < ; i ++)
T[i].id = i, T[i].init(), T[i].build(, , n);
} void check()
{
for(R i = ; i < ; i ++) T[i].get();
for(R i = ; i <= n; i ++) printf("%c", ans[i]);
printf("\n");
} void work()
{
int ll, rr, opt;
for(R i = ; i <= m; i ++)
{
// printf("%d\n", i);
ll = read(), rr = read(), opt = read(), tot = ll - ;
if(opt)
{
for(R j = ; j < ; j ++)
{
add = t = ;
T[j].find(, ll, rr);
if(!add) continue;
T[j].change(, ll, rr);
t = ;
T[j].change(, tot + , tot + add);
tot += add;
}
//check();
}
else
{
for(R j = ; j >= ; j --)
{
add = t = ;
T[j].find(, ll, rr);
if(!add) continue;
T[j].change(, ll, rr);
t = ;
T[j].change(, tot + , tot + add);
tot += add;
}
// check();
}
}
for(R i = ; i < ; i ++) T[i].get();
for(R i = ; i <= n; i ++) printf("%c", ans[i]);
printf("\n");
} int main()
{
//freopen("string6.in", "r", stdin);
pre();
work();
//fclose(stdin);
return ;
}

CF#312 558e A Simple Task的更多相关文章

  1. CF #312 E. A Simple Task 线段树

    题目链接:http://codeforces.com/problemset/problem/558/E 给一个字符串,每次对一个区间内的子串进行升序或者降序的排列,问最后字符串什么样子. 对于字符串排 ...

  2. 计数排序 + 线段树优化 --- Codeforces 558E : A Simple Task

    E. A Simple Task Problem's Link: http://codeforces.com/problemset/problem/558/E Mean: 给定一个字符串,有q次操作, ...

  3. Codeforces 558E A Simple Task (计数排序&&线段树优化)

    题目链接:http://codeforces.com/contest/558/problem/E E. A Simple Task time limit per test5 seconds memor ...

  4. Codeforces 558E A Simple Task(权值线段树)

    题目链接  A Simple Task 题意  给出一个小写字母序列和若干操作.每个操作为对给定区间进行升序排序或降序排序. 考虑权值线段树. 建立26棵权值线段树.每次操作的时候先把26棵线段树上的 ...

  5. Codeforces 558E A Simple Task

    题意:给定一个字符串,以及m次操作,每次操作对字符串的一个子区间进行升序或降序排序,求m次操作后的串 考虑桶排,发现线段树可以模拟桶排的过程,所以对26个字母分别建立线段树即可 #include< ...

  6. codeforces 558E A Simple Task 线段树

    题目链接 题意较为简单. 思路: 由于仅仅有26个字母,所以用26棵线段树维护就好了,比較easy. #include <iostream> #include <string> ...

  7. Codeforces 558E A Simple Task(计数排序+线段树优化)

    http://codeforces.com/problemset/problem/558/E Examples input 1 abacdabcda output 1 cbcaaaabdd input ...

  8. Codeforces Round #312 (Div. 2) E. A Simple Task 线段树

    E. A Simple Task 题目连接: http://www.codeforces.com/contest/558/problem/E Description This task is very ...

  9. Codeforces Round #312 (Div. 2) E. A Simple Task 线段树+计数排序

    题目链接: http://codeforces.com/problemset/problem/558/E E. A Simple Task time limit per test5 secondsme ...

随机推荐

  1. dsp5509的中断系统

    1. DSP5509有32个中断,中断分为软件中断和硬件中断,同时软件中断不可以屏蔽.软件中断由指令触发.55x在中断时DSP会自动保存ST0_55.ST1_55.ST2_55三个寄存器. 2. 其中 ...

  2. MySQL - 问题集 - Access denied; you need the SUPER privilege for

    当执行存储过程相关操作时,如果出现该错误,则往下看. 打开存储过程,会发现“CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost`”. 由于DEFI ...

  3. vim中project多标签和多窗口的使用

    1.打开多个窗口 打开多个窗口的命令以下几个: 横向切割窗口 :new+窗口名(保存后就是文件名) :split+窗口名,也可以简写为:sp+窗口名 纵向切割窗口名 :vsplit+窗口名,也可以简写 ...

  4. 解决CentOS下可以ping通ip ping不通域名

    现象:1. ping不通域名,比如 www.qq.com 2. 可以ping通ip,比如 61.135.157.156 分析:1. 查看DNS配置文件 /etc/resolve.conf, 里面的服务 ...

  5. nginx 路由配置

    nginx中location对url匹配: 语法:location [=|~|~*|^~] /uri/ { … } 当匹配中符合条件的location,则执行内部指令:如果使用正则表达式,必须使用~* ...

  6. 「日常训练」Kefa and Dishes(Codeforces Round #321 Div. 2 D)

    题意与分析(CodeForces 580D) 一个人有\(n\)道菜,然后要点\(m\)道菜,每道菜有一个美味程度:然后给你了很多个关系,表示如果\(x\)刚好在\(y\)前面做的话,他的美味程度就会 ...

  7. Appium(Python)API

    1.创建新的会话desired_caps = desired_caps = {  'platformName': 'Android',  'platformVersion': '7.0',  'dev ...

  8. selenium元素定位(三)

    使用selenium就不可避免的要提到界面元素定位,通过元素定位来实现一系列的逻辑操作. selenium提供了8中元素定位的方式: id.name.class name.tag name.link ...

  9. 蓝牙ble数据转语音实现Android AudioRecord方法推荐

    蓝牙ble数据转语音实现Android AudioRecord方法推荐 教程  欢迎走进zozo的学习之旅. 概述 蓝牙BLE又称bluetooth smart,主打的是低功耗和快速链接,所以在支持的 ...

  10. C语言实训——扑克牌洗牌程序

    说明此程序本来是21点扑克程序的一个被调函数,在这里我单独将它拿出来作为一个小程序. #include<stdio.h> #include<time.h> #include&l ...