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. [Luogu3121][USACO15FEB]审查Censoring

    题面 sol 开一个栈记录依次经过的\(AC\)自动机上的节点编号以及这一次的字母,若匹配到一个串就直接弹掉栈顶的\(len\)个元素,\(len\)为匹配到的模式串长度.弹栈顶直接\(top-=le ...

  2. postgresql搭建从库

    postgresql搭建从库 master  10.40.196.27 slave   10.40.55.69 需求:master和slave作为主从流复制,当master宕机后,slave切换为新主 ...

  3. ssm实现分页查询

    ssm整合实现分页查询 一.通过limit查询语句实现分页,并展示 1.mapper.xml配置 <select id="selectUsersByPage" paramet ...

  4. Python使用Scrapy框架爬取数据存入CSV文件(Python爬虫实战4)

    1. Scrapy框架 Scrapy是python下实现爬虫功能的框架,能够将数据解析.数据处理.数据存储合为一体功能的爬虫框架. 2. Scrapy安装 1. 安装依赖包 yum install g ...

  5. Java计算当前日期前后几天是哪一天:

    计算1900年11月19日往后1000天是哪一天 import java.util.Calendar; import java.util.Date; public class Main { publi ...

  6. Sharepoint对List增删改操作

    在sharepoint的开发过程中,用得最多的,就是获取sharepoint的列表数据,以及对其进行一系列的增删改查等操作,这里主要是记录一些常用的操作,通过对象模型方式对数据进行增删改查. 由于sh ...

  7. 读取超大Excel(39万行数据)

    有个学长需要处理Excel数据,Excel数据共有39W,将数据读取后处理并导出数据.最开始尝试了 NPOI ,发现NPOI 并不能完成该项任务,随后尝试引用的com组件:Microsoft.Offi ...

  8. null和undefined的异同

    相同点: 都表示值得空缺,二者往往可以互换,用“==”相等运算符判断两个是相等的,要用“===”判断. 在希望值是布尔类型的地方,他们的值都是假值,和“false”类似. 都不包含属性和方法. 使用& ...

  9. python 重要的日志模块logging

    一,logging模块简介 logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级.日志保存路径.日志文件回滚等:相比print,具备如下优点: 可以通过设置不同 ...

  10. jsp的四种范围

    jsp有四种范围,可以说是四种对象,这四种对象对应不同的作用范围,所以我们说jsp中的四种范围,这四种范围作用域由大到小分别是page>request>session>applica ...