Codeforces Round #312 (Div. 2) E. A Simple Task 线段树(未敲)

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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值