Summer Training day6 codeforces240F 线段树、回文串

来源:互联网 发布:sybase数据库这么登录 编辑:程序博客网 时间:2024/06/08 06:46

F. TorCoder
time limit per test
3 seconds
memory limit per test
256 megabytes
input
input.txt
output
output.txt

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.

Input

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.

Output

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.

Examples
input
7 2aabcbaa1 35 7
output
abacaba
input
3 2abc1 22 3
output
abc
Note

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.


题解:我们对整个字符串建立26颗线段树,每个线段树维护在某个位置是否有该字母(用1和0表示)。

对于系统查询的区间,我们求出区间长度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*/





原创粉丝点击