• CF #312 E. A Simple Task 线段树


    题目链接:http://codeforces.com/problemset/problem/558/E

    给一个字符串,每次对一个区间内的子串进行升序或者降序的排列,问最后字符串什么样子。

    对于字符串排序,计数排序是比一般的排序要快的,但是仍然不能解决本问题。

    建立26个线段树,用于统计某个字符在某个区间的情况。

    那么如果对【L,R】排序,则先统计所有字符在其中的情况,并且清空该区间,根据每个字符的数量,从a到z去填充应该在的小区间。

      1 #include <iostream>
      2 #include <vector>
      3 #include <algorithm>
      4 #include <string>
      5 #include <string.h>
      6 #include <stdio.h>
      7 #include <math.h>
      8 #include <stdlib.h>
      9 #include <queue>
     10 #include <stack>
     11 #include <map>
     12 #include <set>
     13 #include <ctime>
     14 #include <numeric>
     15 #include <cassert>
     16 
     17 using namespace std;
     18 
     19 const int N=1e5+100;
     20 
     21 char s[N];
     22 
     23 struct SegmentTree {
     24     #define M N*4
     25     int val[M];
     26     int flag[M];
     27     void up(int rt) {
     28         val[rt]=val[rt<<1]+val[rt<<1|1];
     29     }
     30     void build(int l,int r,int rt) {
     31         if (l==r) {
     32             val[rt]=0;
     33             flag[rt]=-1;
     34             return;
     35         }
     36         int m=(l+r)>>1;
     37         build(l,m,rt<<1);
     38         build(m+1,r,rt<<1|1);
     39         up(rt);
     40     }
     41     void down(int rt,int m=0) {
     42         if (flag[rt]!=-1) {
     43             flag[rt<<1]=flag[rt];
     44             flag[rt<<1|1]=flag[rt];
     45             if (flag[rt]==1){
     46                 val[rt<<1]=m-(m>>1);
     47                 val[rt<<1|1]=(m>>1);
     48             }
     49             else {
     50                 val[rt<<1]=0;
     51                 val[rt<<1|1]=0;
     52             }
     53             flag[rt]=-1;
     54         }
     55     }
     56     void update(int p,int c,int l,int r,int rt) {
     57         if (l==r) {
     58             val[rt]=c;
     59             return;
     60         }
     61         down(rt,r-l+1);
     62         int m=(l+r)>>1;
     63         if (p<=m)
     64             update(p,c,l,m,rt<<1);
     65         else
     66             update(p,c,m+1,r,rt<<1|1);
     67         up(rt);
     68     }
     69     void update(int L,int R,bool c,int l,int r,int rt) {
     70         if (L<=l&&r<=R) {
     71             val[rt]=c?(r-l+1):0;
     72             flag[rt]=c;
     73             return;
     74         }
     75         down(rt,r-l+1);
     76         int m=(l+r)>>1;
     77         if (L<=m) update(L,R,c,l,m,rt<<1);
     78         if (R>m) update(L,R,c,m+1,r,rt<<1|1);
     79         up(rt);
     80     }
     81     int query(int p,int l,int r,int rt) {
     82         if (l==r) {
     83             return val[rt];
     84         }
     85         down(rt,r-l+1);
     86         int m=(l+r>>1);
     87         if (p<=m) return query(p,l,m,rt<<1);
     88         else return query(p,m+1,r,rt<<1|1);
     89     }
     90     int query(int L,int R,int l,int r,int rt) {
     91         if (L<=l&&r<=R) {
     92             return val[rt];
     93         }
     94         down(rt,r-l+1);
     95         int m=(l+r)>>1;
     96         int ret=0;
     97         if (L<=m) ret+=query(L,R,l,m,rt<<1);
     98         if (R>m) ret+=query(L,R,m+1,r,rt<<1|1);
     99         return ret;
    100     }
    101     #undef M
    102 }seg[26];
    103 
    104 int main() {
    105     int n,q;
    106     scanf("%d %d",&n,&q);
    107     scanf("%s",s+1);
    108     for (int i=0;i<26;i++)
    109         seg[i].build(1,n,1);
    110     for (int i=1;i<=n;i++) {
    111         int p=s[i]-'a';
    112         seg[p].update(i,1,1,n,1);
    113         //cout<<p<<" xxx"<<endl;
    114     }
    115     while (q--) {
    116         int l,r,t;
    117         scanf("%d %d %d",&l,&r,&t);
    118         int cnt[26];
    119         for (int i=0;i<26;i++) {
    120             cnt[i]=seg[i].query(l,r,1,n,1);
    121             if (cnt[i]>0){
    122                 seg[i].update(l,r,0,1,n,1);
    123             }
    124         }
    125         if (t==1) {
    126             for (int i=0;i<26;l+=cnt[i++]){
    127                 if (cnt[i]==0) continue;
    128                 seg[i].update(l,l+cnt[i]-1,1,1,n,1);
    129             }
    130         }
    131         else {
    132             for (int i=25;i>=0;l+=cnt[i--]){
    133                 if (cnt[i]==0) continue;
    134                 seg[i].update(l,l+cnt[i]-1,1,1,n,1);
    135             }
    136         }
    137     }
    138     for (int i=1;i<=n;i++) {
    139         for (int j=0;j<26;j++){
    140             if (seg[j].query(i,1,n,1)) {
    141                 s[i]='a'+j;
    142                 break;
    143             }
    144         }
    145     }
    146     s[n+1]=0;
    147     printf("%s
    ",s+1);
    148     return 0;
    149 }
    View Code
  • 相关阅读:
    Eclipse汉化教程
    php课程---文件操作及文件上传的代码总结
    php课程---Json格式规范需要注意的小细节
    php课程---php使用PDO方法详解(转)
    php课程---随机数
    php课程---Ajax(老师详解)
    php课程---JavaScript与Jquery的区别
    php课程---JavaScript与Jquery的区别(转)
    php课程---初学PDO
    php课程---练习(联系人信息表)
  • 原文地址:https://www.cnblogs.com/micrari/p/5245460.html
Copyright © 2020-2023  润新知