zoukankan      html  css  js  c++  java
  • JZOJ P5829 string 线段树

    *题意:2个操作,1:[l,r]升序排序,2:[l,r]降序排序,最后输出序列

    *线段树维护:[l,r]区间的字母是什么(必须完全覆盖),这样我们求字母个数的时候就等于(r-l+1)

    *和普通线段树的区别:

    1.建树的pushup:当左区间和右区间都是同一个字母,当前区间也是同一个字母

    il int rs(int x){return x<<1|1;}
    il void pushup(int x){
        if (tree[ls(x)].num==tree[rs(x)].num) tree[x].num=tree[ls(x)].num;
    }

    2.修改和查询的pushdown:下传之后因为排序,字母不在原来的位置,所以要清零

    il void pushdown(int x){
        if (tree[x].num) tree[ls(x)].num=tree[x].num,tree[rs(x)].num=tree[x].num,tree[x].num=0;
    }

    最后输出的时候我们查询[i,i]这个单位区间,哪个字母的个数为1,就输出,记得清零

    完整代码,会线段树的看代码应该会更清晰:

     1 #include <iostream>
     2 #include <algorithm>
     3 #include <cstdio>
     4 #include <cstring>
     5 #define il inline
     6 using namespace std;
     7 const int maxn=1e6;
     8 int n,m,l,r,mark,f[30];
     9 char a[maxn];
    10 struct node{
    11     int num;
    12 }tree[4*maxn];
    13 il int ls(int x){return x<<1;}
    14 il int rs(int x){return x<<1|1;}
    15 il void pushup(int x){
    16     if (tree[ls(x)].num==tree[rs(x)].num) tree[x].num=tree[ls(x)].num;
    17 }
    18 il void build(int x,int l,int r){
    19     if (l==r){int pos=a[l]-'a'+1;tree[x].num=pos;return;}
    20     int mid=(l+r)>>1;
    21     build(ls(x),l,mid); build(rs(x),mid+1,r);
    22     pushup(x);
    23 }
    24 il void pushdown(int x){
    25     if (tree[x].num) tree[ls(x)].num=tree[x].num,tree[rs(x)].num=tree[x].num,tree[x].num=0;
    26 }
    27 il void query(int x,int l,int r,int nl,int nr){
    28     if (nl<=l&&r<=nr&&tree[x].num!=0){f[tree[x].num]+=l-r+1;return;}
    29     int mid=(l+r)>>1;
    30     pushdown(x);
    31     if (nl<=mid) query(ls(x),l,mid,nl,nr);
    32     if (nr>mid) query(rs(x),mid+1,r,nl,nr);
    33 }
    34 il void update(int x,int l,int r,int nl,int nr,int i){
    35 //    cout<<1<<endl;
    36     if (nl<=l&&r<=nr||tree[x].num==i){tree[x].num=i;return;}
    37     int mid=(l+r)>>1;
    38     pushdown(x);
    39     if (nl<=mid) update(ls(x),l,mid,nl,nr,i);
    40     if (nr>mid) update(rs(x),mid+1,r,nl,nr,i);
    41     pushup(x);
    42 }
    43 int main(){
    44     scanf ("%d%d",&n,&m);
    45     getchar();
    46     for (int i = 1;i <= n;i++) scanf ("%c",&a[i]);
    47     build(1,1,n); 
    48     for (int i = 1;i <= m;i++){
    49         memset(f,0,sizeof(f));
    50         scanf ("%d%d%d",&l,&r,&mark);
    51         query(1,1,n,l,r);
    52         if (mark){
    53             for (int i = 1;i <= 26;i++){
    54                 if (f[i]) update(1,1,n,l,l+f[i]-1,i),l=l+f[i];
    55             }
    56         }
    57         else {
    58             for (int i = 26;i >= 1;i--){
    59                 if (f[i]) update(1,1,n,l,l+f[i]-1,i),l=l+f[i];
    60             }
    61         }
    62     }
    63     for (int i = 1;i <= n;i++){
    64         for (int j = 1;j <= 26;j++){
    65             memset(f,0,sizeof(f));
    66             query(1,1,n,i,i);
    67             if (f[j]){char tmp='a'+j-1;cout<<tmp;break;}
    68         }
    69     }
    70     return 0;
    71     
    72 }
  • 相关阅读:
    software architect
    bmh算法
    程序动态切片技术研究
    chm便捷制作
    protobuffer源码解读
    字符串搜索算法比较
    软件架构重组:实践需要和当前做法
    游戏素材制作
    ea(enterprise architect) 相关资料集锦
    vs开启工程非常卡分析和解决
  • 原文地址:https://www.cnblogs.com/very-beginning/p/13591430.html
Copyright © 2011-2022 走看看