E. A Simple Task
题目连接:
http://www.codeforces.com/contest/558/problem/E
Description
This task is very simple. Given a string S of length n and q queries each query is on the format i j k which means sort the substring consisting of the characters from i to j in non-decreasing order if k = 1 or in non-increasing order if k = 0.
Output the final string after applying the queries.
Input
The first line will contain two integers n, q (1 ≤ n ≤ 105, 0 ≤ q ≤ 50 000), the length of the string and the number of queries respectively.
Next line contains a string S itself. It contains only lowercase English letters.
Next q lines will contain three integers each i, j, k (1 ≤ i ≤ j ≤ n, ).
Output
Output one line, the string S after applying the queries.
Sample Input
10 5
abacdabcda
7 10 0
5 8 1
1 4 0
3 6 0
7 10 1
Sample Output
cbcaaaabdd
Hint
题意
给你n个字符,一共俩操作,l到r区间升序排序,l到r降序排序
字符集26.
让你输出最后的字符样子。
题解:
考虑计数排序,我们用线段树维护计数排序就好了,这样复杂度是26*q*logn
感觉自己智商还是涨了一波……
558E - A Simple Task
In this problem we will be using counting sort. So for each query we will count the number of occurrences for each character, and then update the range like this
for(int j=x;j<=y;j++)
cnt[s[j] - ‘a’]++;
ind = 0;
for(int j=x;j<=y;j++)
{
while(cnt[ind] == 0)
ind++;
s[j] = ind + ‘a’;
cnt[ind]–;
}
But this is too slow. We want a data structure that can support the above operations in appropriate time.
Let’s make 26 segment trees each one for each character. Now for each query let’s get the count of every character in the range, and then arrange them and update each segment tree with the new values. We will have to use lazy propagation technique for updating ranges.
Time complexity: where sz is the size of the alphabet (i.e. = 26).
暂时看不懂。。。。
using namespace std;
int tree[400005][27], lazy[400005][27];
char s[100005];
void build(int i,int L,int R)
{
if(L == R)
{
tree[i][s[L] - 'a'] = 1;
for(int j=0;j<26;j++)
lazy[i][j] = -1;
return ;
}
build(i*2 + 1, L, (L + R) / 2);
build(i*2 + 2, (L + R) / 2 + 1, R);
for(int j=0;j<26;j++)
{
lazy[i][j] = -1;
tree[i][j] = tree[i*2 + 1][j] + tree[i*2 + 2][j];
}
}
void update(int i, int L, int R, int x, int y, int val, int j)
{
if(lazy[i][j] != -1)
{
tree[i][j] = lazy[i][j] * (R - L + 1);
if(L != R)
{
lazy[i*2+1][j] = lazy[i][j];
lazy[i*2+2][j] = lazy[i][j];
}
lazy[i][j] = -1;
}
if(L >= x && R <= y)
{
lazy[i][j] = val;
tree[i][j] = lazy[i][j] * (R - L + 1);
if(L != R)
{
lazy[i*2+1][j] = lazy[i][j];
lazy[i*2+2][j] = lazy[i][j];
}
lazy[i][j] = -1;
return;
}
if(L > y || R < x)
return;
update(i*2 + 1, L, (L + R) / 2, x, y, val, j);
update(i*2 + 2, (L + R) / 2 + 1, R, x, y, val, j);
tree[i][j] = tree[i*2 + 1][j] + tree[i*2 + 2][j];
}
int query(int i, int L, int R, int x, int y, int j)
{
if(lazy[i][j] != -1)
{
tree[i][j] = lazy[i][j] * (R - L + 1);
if(L != R)
{
lazy[i*2+1][j] = lazy[i][j];
lazy[i*2+2][j] = lazy[i][j];
}
lazy[i][j] = -1;
}
if(L >= x && R <= y)
return tree[i][j];
if(L > y || R < x)
return 0;
return query(i*2 + 1, L, (L + R) / 2, x, y, j) + query(i*2 + 2, (L + R) / 2 + 1, R, x, y, j);
}
void get(int i, int L, int R, int j)
{
if(lazy[i][j] != -1)
{
tree[i][j] = lazy[i][j] * (R - L + 1);
if(L != R)
{
lazy[i*2+1][j] = lazy[i][j];
lazy[i*2+2][j] = lazy[i][j];
}
lazy[i][j] = -1;
}
if(!tree[i][j])
return ;
if(L == R)
{
s[L] = j + 'a';
return;
}
get(i*2 + 1, L, (L + R) / 2, j);
get(i*2 + 2, (L + R) / 2 + 1, R, j);
}
int cnt[26];
int main()
{
//ios_base::sync_with_stdio(0);
//freopen("test0.txt", "r", stdin);
//freopen("lca.out", "w", stdout);
int n, q, x, y, up;
scanf("%d %d", &n, &q);
scanf("%s", s);
build(0, 0, n - 1);
for(int i=0;i<q;i++)
{
scanf("%d %d %d", &x, &y, &up);
x--, y--;
for(int j=0;j<26;j++)
cnt[j] = query(0, 0, n - 1, x, y, j);
int curr = x;
if(!up) curr = y;
for(int j=0;j<26;j++)
{
if(!cnt[j]) continue;
update(0, 0, n - 1, x, y, 0, j);
if(up)
{
update(0, 0, n - 1, curr, curr + cnt[j] - 1, 1, j);
curr+=cnt[j];
}
else
{
update(0, 0, n - 1, curr - cnt[j] + 1, curr, 1, j);
curr-=cnt[j];
}
}
}
for(int i=0;i<26;i++)
get(0, 0, n - 1, i);
printf("%s", s);
return 0;
}
#include<bits/stdc++.h>
using namespace std;
#define maxn 100100
#define lc (o<<1)
#define rc ((o<<1)|1)
#define mid ((l+r)>>1)
char s[maxn];
struct Seg
{
char c;
int v[maxn<<2];
int mar[maxn<<2],add[maxn<<2];
void up(int o){v[o]=v[lc]+v[rc];}
void build(int o,int l,int r)
{
if(l==r)
{
v[o]=(s[l]==c);
return;
}
build(lc,l,mid);
build(rc,mid+1,r);
up(o);
}
void deal_clear(int o)
{
mar[o]=1;
add[o]=v[o]=0;
}
void deal_add(int o,int l,int r,int val)
{
add[o]+=val;
v[o]+=(r-l+1)*val;
}
void down(int o,int l,int r)
{
if(mar[o])
{
deal_clear(lc);
deal_clear(rc);
mar[o]=0;
}
if(add[o]!=0)
{
deal_add(lc,l,mid,add[o]);
deal_add(rc,mid+1,r,add[o]);
add[o]=0;
}
}
void update_add(int o,int l,int r,int y1,int y2,int val)
{
if(y1<=l&&y2>=r)
{
deal_add(o,l,r,val);
return;
}
down(o,l,r);
if(y1<=mid) update_add(lc,l,mid,y1,y2,val);
if(y2>mid) update_add(rc,mid+1,r,y1,y2,val);
up(o);
}
void update_clear(int o,int l,int r,int y1,int y2)
{
if(y1<=l&&y2>=r)
{
deal_clear(o);
return;
}
down(o,l,r);
if(y1<=mid) update_clear(lc,l,mid,y1,y2);
if(y2>mid) update_clear(rc,mid+1,r,y1,y2);
up(o);
}
int query(int o,int l,int r,int y1,int y2)
{
if(y1<=l&&y2>=r) return v[o];
down(o,l,r);
int ans=0;
if(y1<=mid) ans+=query(lc,l,mid,y1,y2);
if(y2>mid) ans+=query(rc,mid+1,r,y1,y2);
return ans;
}
void dfs(int o,int l,int r)
{
if(!v[o]) return;
if(l==r)
{
s[l]=c;
return;
}
down(o,l,r);
dfs(lc,l,mid); dfs(rc,mid+1,r);
}
}sg[26];
int n,m,cnt[26];
int main()
{
scanf("%d%d",&n,&m);
scanf("%s",s+1);
for(int i=0;i<26;++i)
{
sg[i].c='a'+i;
sg[i].build(1,1,n);
}
while(m--)
{
int l,r,typ;
scanf("%d%d%d",&l,&r,&typ);
if(l==r) continue;
for(int i=0;i<26;++i) cnt[i]=sg[i].query(1,1,n,l,r);
int now=l;
if(typ)
{
for(int i=0;i<26;++i)
if(cnt[i])
{
sg[i].update_clear(1,1,n,l,r);
sg[i].update_add(1,1,n,now,now+cnt[i]-1,1);
now+=cnt[i];
}
}
else
{
for(int i=25;i>=0;--i)
if(cnt[i])
{
sg[i].update_clear(1,1,n,l,r);
sg[i].update_add(1,1,n,now,now+cnt[i]-1,1);
now+=cnt[i];
}
}
}
for(int i=0;i<26;++i) sg[i].dfs(1,1,n);
printf("%s",s+1);
return 0;
}