Codeforces Round #312 (Div. 2) E. A Simple Task

  题目大意就是给一个字符串,然后多个操作,每次操作可以把每一段区间的字符进行升序或者降序排序,问最终的字符串是多少。

  一开始只考虑字符串中字符'a'的情况,假设操作区间[L,R]中有x个'a',那么一次操作后,这x个'a'要么去最左(升序),要么去最右(降序),我们可以建立一颗线段树来维护这样的操作,字符'a'出现的位置值为1,否则为0,那么q次操作后,最后值为1的地方填的就是'a'了。

  在考虑字符'a'和'b'的情况,操作的情况和上面类似,字符'a'和'b'出现的位置值为1,否则为0,q次操作后,如果一个位置的值为1,并且该位置没有填写'a',那么这个位置就填写'b'。接下来的情况以此类推,一直做到z,复杂度O(26*qlogn)。

  

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<map>
  4 #include<cstring>
  5 #include<vector>
  6 #include<cmath>
  7 #include<iostream>
  8 #include<string>
  9 #define N 1000010
 10 #define M 1010
 11 #define P 1000000007
 12 using namespace std;
 13 int v[N],s[N],l[N],r[N],tt;
 14 int L[N],R[N],typ[N],n,q,i,j,tmp,ans[N];
 15 string str;
 16 void build(int x,int a,int b)
 17 {
 18     int m;
 19     l[x]=a;r[x]=b;
 20     if (x>tt) tt=x;
 21     if (b-a>1)
 22     {
 23         m=(a+b)>>1;
 24         build(2*x,a,m);
 25         build(2*x+1,m,b);   
 26     }
 27     v[x]=-1;
 28 }
 29 void clean(int x)
 30 {
 31     if (v[x]!=-1)
 32     {
 33         s[x]=(r[x]-l[x])*v[x];
 34         if (2*x<=tt) v[2*x]=v[x];
 35         if (2*x+1<=tt) v[2*x+1]=v[x];
 36         v[x]=-1;
 37     }
 38 }
 39 void change(int x,int a,int b,int c)
 40 {
 41     int m;
 42     clean(x);
 43     if ((a<=l[x])&&(r[x]<=b))
 44     {
 45         v[x]=c;
 46         return;
 47     }
 48     m=(l[x]+r[x])>>1;
 49     if (a<m) change(2*x,a,b,c);
 50     if (m<b) change(2*x+1,a,b,c);
 51     clean(2*x);clean(2*x+1);
 52     s[x]=s[2*x]+s[2*x+1];
 53 }
 54 int query(int x,int a,int b)
 55 {
 56     int m,ans=0;
 57     clean(x);
 58     if ((a<=l[x])&&(r[x]<=b))
 59         return s[x];
 60     m=(l[x]+r[x])>>1;
 61     if (a<m) ans+=query(2*x,a,b);
 62     if (m<b) ans+=query(2*x+1,a,b);
 63     return ans;
 64 }
 65 int main()
 66 {
 67     cin>>n>>q;
 68     cin>>str;
 69     build(1,0,n);
 70     for (i=1;i<=q;i++)
 71     cin>>L[i]>>R[i]>>typ[i];
 72     
 73     for (j=1;j<=26;j++)
 74     {
 75         change(1,0,n,0);
 76         for (i=0;i<n;i++)
 77         if (str[i]-96<=j)
 78         change(1,i,i+1,1);
 79         for (i=1;i<=q;i++)
 80         {
 81             tmp=query(1,L[i]-1,R[i]);
 82             change(1,L[i]-1,R[i],0);
 83             if (tmp)
 84             {
 85             if (typ[i]==0)
 86             change(1,R[i]-tmp,R[i],1);
 87             else
 88             change(1,L[i]-1,L[i]-1+tmp,1);
 89             }
 90         }
 91         
 92         for (i=1;i<=n;i++)
 93         if ((query(1,i-1,i)==1)&&(ans[i]==0))
 94         ans[i]=96+j;
 95     }
 96     
 97     for (i=1;i<=n;i++)
 98     {
 99         char ch=ans[i];
100         cout<<ch;
101     }
102 }

 

转载于:https://www.cnblogs.com/fzmh/p/4648572.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值