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 2
aabcbaa
1 3
5 7
output
abacaba
input
3 2
abc
1 2
2 3
output
abc
Note

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.

题意:

给定一个长为n的字符串。

有m次操作,每次操作将[l,r]这些位置的字符进行重排,得到字典序最小的回文字符串,如果无法操作就不进行。

求m次操作后的字符串。

26颗线段树 维护区间 每个字母的出现次数

为了使得字典序最小,贪心的放进去。

要做的操作是:区间查询和,区间赋值为1,区间赋值为0。

做麻烦了,其实只需要一颗线段树就可以。。。

#include<cstdio>
#include<cstring>
#define N 100001
#define M N*50
using namespace std;
int cnt;
int root[],tot[],pre[],suc[];
struct node
{
int lc,rc,sum1;
bool all0,all1;
bool f0,f1;
}tr[M];
void up(int k)
{
tr[k].all0=tr[tr[k].lc].all0&tr[tr[k].rc].all0;
tr[k].all1=tr[tr[k].lc].all1&tr[tr[k].rc].all1;
tr[k].sum1=tr[tr[k].lc].sum1+tr[tr[k].rc].sum1;
}
void insert(int &k,int l,int r,int pos)
{
if(!k) k=++cnt;
tr[k].sum1++;
if(l==r)
{
tr[k].all1=true;
return;
}
int mid=l+r>>;
if(pos<=mid) insert(tr[k].lc,l,mid,pos);
else insert(tr[k].rc,mid+,r,pos);
up(k);
}
void down(int k,int l,int r)
{
if(tr[k].f0)
{
if(!tr[k].lc) tr[k].lc=++cnt;
if(!tr[k].rc) tr[k].rc=++cnt;
tr[tr[k].lc].all0=tr[tr[k].lc].f0=true;
tr[tr[k].lc].all1=tr[tr[k].lc].f1=false;
tr[tr[k].rc].all0=tr[tr[k].rc].f0=true;
tr[tr[k].rc].all1=tr[tr[k].rc].f1=false;
tr[tr[k].lc].sum1=tr[tr[k].rc].sum1=;
tr[k].f0=false;
}
else
{
if(!tr[k].lc) tr[k].lc=++cnt;
if(!tr[k].rc) tr[k].rc=++cnt;
tr[tr[k].lc].all0=tr[tr[k].lc].f0=false;
tr[tr[k].lc].all1=tr[tr[k].lc].f1=true;
tr[tr[k].rc].all0=tr[tr[k].rc].f0=false;
tr[tr[k].rc].all1=tr[tr[k].rc].f1=true;
int mid=l+r>>;
tr[tr[k].lc].sum1=mid-l+;
tr[tr[k].rc].sum1=r-mid;
tr[k].f1=false;
}
}
void change0(int k,int l,int r,int opl,int opr)
{
if(!k) k=++cnt;
if(l>=opl && r<=opr)
{
tr[k].all0=tr[k].f0=true;
tr[k].all1=tr[k].f1=false;
tr[k].sum1=;
return;
}
if(tr[k].f0 || tr[k].f1) down(k,l,r);
int mid=l+r>>;
if(opl<=mid ) change0(tr[k].lc,l,mid,opl,opr);
if(opr>mid ) change0(tr[k].rc,mid+,r,opl,opr);
up(k);
}
void change1(int &k,int l,int r,int opl,int opr)
{
if(!k) k=++cnt;
if(tr[k].all1) return;
if(l>=opl && r<=opr)
{
tr[k].all0=tr[k].f0=false;
tr[k].all1=tr[k].f1=true;
tr[k].sum1=r-l+;
return;
}
if(tr[k].f0 || tr[k].f1) down(k,l,r);
int mid=l+r>>;
if(opl<=mid ) change1(tr[k].lc,l,mid,opl,opr);
if(opr>mid ) change1(tr[k].rc,mid+,r,opl,opr);
up(k);
}
int query(int k,int l,int r,int opl,int opr)
{
if(tr[k].all0) return ;
if(l>=opl && r<=opr) return tr[k].sum1;
if(tr[k].f0 || tr[k].f1) down(k,l,r);
int mid=l+r>>,tmp=;
if(opl<=mid && tr[k].lc) tmp+=query(tr[k].lc,l,mid,opl,opr);
if(opr>mid && tr[k].rc) tmp+=query(tr[k].rc,mid+,r,opl,opr);
return tmp;
}
bool point_query(int k,int l,int r,int pos)
{
if(l==r) return tr[k].sum1;
if(tr[k].f0 || tr[k].f1) down(k,l,r);
int mid=l+r>>;
if(pos<=mid)
{
if(tr[k].lc) return point_query(tr[k].lc,l,mid,pos);
return false;
}
else
{
if(tr[k].rc) return point_query(tr[k].rc,mid+,r,pos);
return false;
}
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
int n,m; char s[N];
scanf("%d%d",&n,&m);
scanf("%s",s);
tr[].all0=true;
for(int i=;i<n;i++) insert(root[s[i]-'a'],,n,i+);
int opl,opr; bool odd,fail;
int od,mid;
while(m--)
{
scanf("%d%d",&opl,&opr);
odd=fail=false; memset(tot,,sizeof(tot)); od=-;
for(int i=;i<;i++)
{
tot[i]=query(root[i],,n,opl,opr);
if(tot[i]%)
if(!odd) odd=true,od=i,tot[i]--;
else { fail=true; break; }
}
if(fail) continue;
for(int i=;i<;i++)
if(tot[i] || od==i) change0(root[i],,n,opl,opr); pre[]=tot[];
for(int i=;i<;i++) pre[i]=pre[i-]+tot[i]; suc[]=tot[];
for(int i=;i<;i++) suc[i]=suc[i-]+tot[-i]; if(tot[]) change1(root[],,n,opl,opl+pre[]/-);
for(int i=;i<;i++)
if(tot[i]) change1(root[i],,n,opl+pre[i-]/,opl+pre[i]/-); if(odd) mid=opl+pre[]/,change1(root[od],,n,opl+pre[]/,opl+pre[]/);
else mid=opl+pre[]/-; if(tot[]) change1(root[],,n,mid+,mid+suc[]/);
for(int i=;i<;i++)
if(tot[-i]) change1(root[-i],,n,mid+suc[i-]/+,mid+suc[i]/);
/*for(int i=1;i<=n;i++)
for(int j=0;j<26;j++)
if(point_query(root[j],1,n,i))
{
putchar('a'+j);
break;
}
puts("");*/
}
for(int i=;i<=n;i++)
for(int j=;j<;j++)
if(point_query(root[j],,n,i))
{
putchar('a'+j);
break;
}
}

Codeforces 240 F. TorCoder的更多相关文章

  1. Codeforces 959 F. Mahmoud and Ehab and yet another xor task

    \(>Codeforces\space959 F. Mahmoud\ and\ Ehab\ and\ yet\ another\ xor\ task<\) 题目大意 : 给出一个长度为 \ ...

  2. Codeforces 835 F. Roads in the Kingdom

    \(>Codeforces\space835 F. Roads in the Kingdom<\) 题目大意 : 给你一棵 \(n\) 个点构成的树基环树,你需要删掉一条环边,使其变成一颗 ...

  3. Codeforces 731 F. Video Cards(前缀和)

    Codeforces 731 F. Video Cards 题目大意:给一组数,从中选一个数作lead,要求其他所有数减少为其倍数,再求和.问所求和的最大值. 思路:统计每个数字出现的个数,再做前缀和 ...

  4. Codeforces 797 F Mice and Holes

    http://codeforces.com/problemset/problem/797/F F. Mice and Holes time limit per test             1.5 ...

  5. Codeforces 622 F. The Sum of the k-th Powers

    \(>Codeforces \space 622\ F. The\ Sum\ of\ the\ k-th\ Powers<\) 题目大意 : 给出 \(n, k\),求 \(\sum_{i ...

  6. Codeforces 379 F. New Year Tree

    \(>Codeforces \space 379 F. New Year Tree<\) 题目大意 : 有一棵有 \(4\) 个节点个树,有连边 \((1,2) (1,3) (1,4)\) ...

  7. Codeforces 538 F. A Heap of Heaps

    \(>Codeforces \space 538 F. A Heap of Heaps<\) 题目大意 :给出 \(n\) 个点,编号为 \(1 - n\) ,每个点有点权,将这些点构建成 ...

  8. codeforces 825F F. String Compression dp+kmp找字符串的最小循环节

    /** 题目:F. String Compression 链接:http://codeforces.com/problemset/problem/825/F 题意:压缩字符串后求最小长度. 思路: d ...

  9. [codeforces 618 F] Double Knapsack (抽屉原理)

    题目链接:http://codeforces.com/contest/618/problem/F 题目: 题目大意: 有两个大小为 N 的可重集 A, B, 每个元素都在 1 到 N 之间. 分别找出 ...

随机推荐

  1. haproxy实现会话保持(1):cookie

    */ .hljs { display: block; overflow-x: auto; padding: 0.5em; color: #333; background: #f8f8f8; } .hl ...

  2. 自言自语WEB前端面试题(一)

    刚刚得到通知,明天可能要放半天假,开心的像个200斤的傻子 我怕真是个傻子,是后天 今天的我是依旧痛经的我 于是我又来写博客了 原来,博客竟是痛经良药 接下来请看题,此题,0难度,基本不需要动脑子 J ...

  3. ThreadLocal用例之周期为一次请求的变量

    public class RecordedLocal { private static ThreadLocal<Recorded> local = new ThreadLocal<R ...

  4. gulp配置

    /* gulp配置 */ /* gulp配置 */ var gulp = require('gulp'), concat = require('gulp-concat'), rename = requ ...

  5. CentOS配置本地yum源

    如果CentOS服务器处在内网环境中时,如果缺少依赖手动安装那么会非常麻烦,要花费很多时间来寻找rpm包,现在如果搭建本地的yum源,就非常方便了,使用yum源首先需要一个CentOS安装镜像,去官网 ...

  6. Git分支(5/5) -- 解决合并的冲突

    如果两个分支上都对同一个文件进行了修改, 那么就有可能发生冲突. 首先创建一个分支, 并切换到该分支上: 然后修改index.html, 修改几个地方吧. 然后查看状态, 并commit: 然后切换到 ...

  7. c++趣味之难以发现的bug

    这些bug可能够你喝一壶的. 1.被断言(assert)包含的代码 常发生在切换到release版本时,执行结果乖乖的,最终查找结果是assert括号里的代码在release下是不执行的. 发现:跟踪 ...

  8. protobuf的下载、编译和使用

    一 背景 工作中临时需要使用 protobuf v3.0.2 做消息格式转换,折腾了很久才搞定,这里特意做一个记录. 二 准备工作 全程使用的电脑为公司的win7 64位旗舰版,已经预先安装VS201 ...

  9. 笔记:Spring Cloud Eureka 服务治理

    Spring Cloud Eureka 是 Spring Cloud Netflix 微服务套件的一部分,基于 Netflix Eureka 做了二次封装,主要负责完成微服务架构中的服务治理功能,服务 ...

  10. Javscript的垃圾回收

    和C#.Java一样JavaScript有自动垃圾回收机制,也就是说执行环境会负责管理代码执行过程中使用的内存,在开发过程中就无需考虑内存分配及无用内存的回收问题了.JavaScript垃圾回收的机制 ...