Summer Training day6 codeforces240F 线段树、回文串
来源:互联网 发布:sybase数据库这么登录 编辑:程序博客网 时间:2024/06/08 06:46
A boy named Leo doesn't miss a single TorCoder contest round. On the last TorCoder round number 100666 Leo stumbled over the following problem. He was given a string s, consisting of n lowercase English letters, and m queries. Each query is characterised by a pair of integers li, ri (1 ≤ li ≤ ri ≤ n).
We'll consider the letters in the string numbered from 1 to n from left to right, that is, s = s1s2... sn.
After each query he must swap letters with indexes from li to ri inclusive in string s so as to make substring (li, ri) a palindrome. If there are multiple such letter permutations, you should choose the one where string (li, ri) will be lexicographically minimum. If no such permutation exists, you should ignore the query (that is, not change string s).
Everybody knows that on TorCoder rounds input line and array size limits never exceed 60, so Leo solved this problem easily. Your task is to solve the problem on a little bit larger limits. Given string s and m queries, print the string that results after applying all m queries to string s.
The first input line contains two integers n and m (1 ≤ n, m ≤ 105) — the string length and the number of the queries.
The second line contains string s, consisting of n lowercase Latin letters.
Each of the next m lines contains a pair of integers li, ri (1 ≤ li ≤ ri ≤ n) — a query to apply to the string.
In a single line print the result of applying m queries to string s. Print the queries in the order in which they are given in the input.
7 2aabcbaa1 35 7
abacaba
3 2abc1 22 3
abc
A substring (li, ri) 1 ≤ li ≤ ri ≤ n) of string s = s1s2... sn of length n is a sequence of characters slisli + 1...sri.
A string is a palindrome, if it reads the same from left to right and from right to left.
String x1x2... xp is lexicographically smaller than string y1y2... yq, if either p < q and x1 = y1, x2 = y2, ... , xp = yp, or exists such number r(r < p, r < q), that x1 = y1, x2 = y2, ... , xr = yr and xr + 1 < yr + 1.
对于系统查询的区间,我们求出区间长度len,然后用26颗线段树,分别统计在该区间内,相应的字母有多少个。
如果这个区间的长度为偶数,那么所有的字母数量都应该是偶数。我们这么处理,假设区间为[l,r] a的统计数量有2个,那么我们就先把第0颗线段树的[l,r]区间清零
然后把区间[l,l]和[r,r]进行置1。假设b的统计数量有4个,那么就把第1颗线段树的[l+1,r-1]全部清零,然后[l+1,l+2] , [r-2,r-1]全部置1。
再输出整个字符串的时候,对于每一个位置,在所有的线段树上找,在那棵线段树上就输出那颗线段树所代表的字母。
代码:
#include <iostream>#include <cstdio>#include <algorithm>#include <vector>using namespace std;const int MAXN= 1e5+7;char str[MAXN];struct segtree{char c;int val[MAXN << 2];int mark[MAXN << 2];void pushup(int rt){val[rt] = val[rt*2] + val[rt*2+1];}void pushdown(int rt,int begin,int end){if(mark[rt] == 1){int mid = (begin + end) / 2;val[rt*2] = (mid - begin + 1);val[rt*2+1] = (end - mid);mark[rt*2] = mark[rt*2+1] = mark[rt];}else if (mark[rt] == 2){int mid = (begin + end) / 2;val[rt*2] = 0;val[rt*2+1] = 0;mark[rt*2] = mark[rt*2+1] = mark[rt];}mark[rt] = 0;}void build(int rt,int begin,int end){mark[rt] = 0;if(begin == end){val[rt] = str[begin-1] == c;return ;}int mid = (begin + end) / 2;build(rt*2,begin,mid);build(rt*2+1,mid+1,end);pushup(rt);}void update(int rt,int begin,int end,int ubegin,int uend,int key){//key == 1 set//key == 2 resetif(uend < ubegin) return ;if(begin > uend || ubegin > end){return ;}if(begin >= ubegin && end <= uend){mark[rt] = key;if(key == 1){val[rt] = (end - begin + 1) * 1;}else if(key == 2){val[rt] = 0;}return ;}pushdown(rt,begin,end);int mid = (begin + end) / 2;update(rt*2,begin,mid,ubegin,uend,key);update(rt*2+1,mid+1,end,ubegin,uend,key);pushup(rt);}int query(int rt,int begin,int end,int ubegin,int uend){if(begin > uend || ubegin > end){return 0;}if(begin >= ubegin && end <= uend){return val[rt];}pushdown(rt,begin,end);int mid = (begin + end) / 2;int a = query(rt*2,begin,mid,ubegin,uend);int b = query(rt*2+1,mid+1,end,ubegin,uend);return a + b;}}segs[30];int n, m;int main(){freopen("input.txt","r",stdin);freopen("output.txt","w",stdout);scanf("%d%d",&n,&m);scanf(" %s",str);for(int i = 0;i < 26;i++){segs[i].c = 'a' + i;segs[i].build(1,1,n);}for(int i = 0;i < m;i++){int a,b;scanf("%d%d",&a,&b);int cnt = 0;vector<pair<int,int> > vec;for(int t = 0;t < 26;t++){int nums = segs[t].query(1,1,n,a,b);if(nums % 2) cnt++;if(nums) vec.push_back(make_pair(t,nums));}if(((a-b + 1) % 2 == 0 && cnt > 0) || ((a-b + 1) % 2 != 0 && cnt != 1)) continue;int l = 0;for(int t = 0;t < vec.size();t++){pair<int,int> p = vec[t];int id = p.first;int nums = p.second;segs[id].update(1,1,n,a,b,2);if(nums % 2){segs[id].update(1,1,n,(a+b)/2,(a+b)/2,1);}segs[id].update(1,1,n,a+l,a+l+nums/2-1,1);segs[id].update(1,1,n,b-l-nums/2+1,b-l,1);l += nums/2;}}for(int i = 1;i <= n;i++){for(int t = 0;t < 26;t++){if(segs[t].query(1,1,n,i,i)){putchar(t+ 'a');break;}}}return 0;}/*7 1aabcbaa1 37 1aabcbaa5 7*/
- Summer Training day6 codeforces240F 线段树、回文串
- Summer Training day6 codeforces633G 线段树、bitset
- Summer Training day6 coseforces339D 线段树、位操作
- Summer Training day6 codeforces343D dfs序、线段树
- Summer Training day6 codeforces787D 最短路spfa,线段树建图
- Summer Training day6 codeforces 675D 二叉搜索树
- Summer training day6 codeforces19E 树链剖分,并查集
- Summer Training day6 codeforces 593D LCA+并查集
- Summer Training day6 codeforces292D并查集合并
- 【BNU Summer Training 2014.08.11】 Nested Segments (线段树,离散化)
- Tri_integral Summer Training 6
- BUPT-SUMMER-TRAINING-搜索
- 2017 Summer Training Day1
- Summer Training day4 欧拉降幂
- Summer Training day4 Sumdiv
- After Summer Training.
- UESTC Summer Team Training #2
- BUPT Summer training 1 总结
- <job_demo><Qt>自绘仪表类控件
- POJ
- 8.10
- java 成员变量以及局部变量的区别及存储
- <form>标签提交不转跳的几种方式
- Summer Training day6 codeforces240F 线段树、回文串
- 面向对象六大基本原则、设计模式、工程模式
- HDU
- 带缩略图的轮播图
- 720项目
- Activity切换时生命周期执行顺序
- Manacher算法,O(n)回文子串算法 以及模板题HDU3068最长回文串
- vuex namespaced的作用
- Linux 压缩相关