[Problem Solution] CJOI 2019 Line Segment Tree (Line Segment Tree)

Keywords: PHP

[Problem Solution] CJOI 2019 Line Segment Tree (Line Segment Tree)

The character set is \(26\) and gives you a string that requires you to ascend and descend the intervals.

You find that the character set is (26) and can be barreled. Open a segment tree to maintain this thing.

  • A barrel with each letter in the area.
  • Lazy tag or not

Considering how to modify, you first take out all the nodes in the interval (which are fully included), then count the number of letters in the node, and then sort the buckets. Remove all nodes that are(log n)

After you modify this node, consider putting it back. First, you should always ( ce{pushup}) and then ( ce{pushdown}\) again, where the complexity is \(n\ log ^ 2 n)

Bucket sorting is when you put the big bucket (sorting large interval) into the small bucket (cell), and this operation is \\\\\\\\\\\

So write pushdown like this

inline void pud(const int&pos){
      if(data[pos].tag<0) return;
      int L=data[pos<<1].len,R=data[pos<<1|1].len;
      int *t1=data[pos<<1].buk,*t2=data[pos<<1|1].buk;
      data[pos<<1].tag=data[pos<<1|1].tag=data[pos].tag;
      memset(data[pos<<1].buk,0,sizeof data[pos<<1].buk);
      memset(data[pos<<1|1].buk,0,sizeof data[pos<<1|1].buk);
      if(!data[pos].tag) swap(L,R),t1=data[pos<<1|1].buk,t2=data[pos<<1].buk;
      for(register int t=0,*f=data[pos].buk;t<26;++t) pm[t]=f[t];
      register int now=0;
      while(L>=pm[now]&&now<26) L-=pm[now],t1[now]+=pm[now],pm[now]=0,++now;
      if(L) pm[now]-=L,t1[now]+=L,L=0;
      while(R>=pm[now]&&now<26) R-=pm[now],t2[now]+=pm[now],pm[now]=0,++now;
      if(R) pm[now]-=R,t1[now]+=R,R=0;
      data[pos].tag=-1;
}

Also, strongly condemn the action of \\\\\\\\\\\\\\

The world belongs to Codori when the tyranny is overthrown.

The code has been crushed, or more than 100 lines.

//@winlere
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define midd register int mid=(l+r)>>1
#define lef l,mid,pos<<1
#define rgt mid+1,r,pos<<1|1

using namespace std;  typedef long long ll;
inline int qr(){
      register int ret=0,f=0;
      register char c=getchar();
      while(c<48||c>57)f|=c==45,c=getchar();
      while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
      return f?-ret:ret;

}
const int maxn=1e5+5;
struct E{
      int buk[26],tag,l,r,len;
      E(){memset(buk,0,sizeof buk);tag=-1;l=r=len=0;}
      inline int& operator [](register int x){return buk[x];}
}data[maxn<<2];
int n,m,pm[26],md[26];
vector < int > ve;
inline int qrqr(){
      register char c=getchar();
      while(c<'a'||c>'z') c=getchar();
      return c-'a';
}
inline void pup(const int&pos){
      int *t1=data[pos].buk,*t2=data[pos<<1].buk,*t3=data[pos<<1|1].buk;
      for(register int t=0;t<26;++t) t1[t]=t2[t]+t3[t];
}
inline void pud(const int&pos){
      if(data[pos].tag<0) return;
      int L=data[pos<<1].len,R=data[pos<<1|1].len;
      int *t1=data[pos<<1].buk,*t2=data[pos<<1|1].buk;
      data[pos<<1].tag=data[pos<<1|1].tag=data[pos].tag;
      memset(data[pos<<1].buk,0,sizeof data[pos<<1].buk);
      memset(data[pos<<1|1].buk,0,sizeof data[pos<<1|1].buk);
      if(!data[pos].tag) swap(L,R),t1=data[pos<<1|1].buk,t2=data[pos<<1].buk;
      for(register int t=0,*f=data[pos].buk;t<26;++t) pm[t]=f[t];
      register int now=0;
      while(L>=pm[now]&&now<26) L-=pm[now],t1[now]+=pm[now],pm[now]=0,++now;
      if(L) pm[now]-=L,t1[now]+=L,L=0;
      while(R>=pm[now]&&now<26) R-=pm[now],t2[now]+=pm[now],pm[now]=0,++now;
      if(R) pm[now]-=R,t1[now]+=R,R=0;
      data[pos].tag=-1;
}
void build(const int&l,const int&r,const int&pos){
      data[pos].l=l;data[pos].r=r;data[pos].len=r-l+1;
      if(l==r){  ++data[pos][qrqr()];return;}
      midd;     build(lef);build(rgt);
      pup(pos);
}
void split(const int&L,const int&R,const int&l,const int&r,const int&pos){
      if(L>r||R<l)return;
      if(L<=l&&r<=R){
        ve.push_back(pos);
        return;
      }
      midd;pud(pos);
      split(L,R,lef);split(L,R,rgt);
}
void getup(const int&pos){if(!pos)return; pup(pos); getup(pos>>1);  }      
void ans(const int&l,const int&r,const int&pos){
      if(l==r) for(register int t=0,*f=data[pos].buk;t<26;++t) if(f[t]) {putchar(t+'a');return;}
      midd;pud(pos);
      ans(lef);ans(rgt);
}
void mody(const int&L,const int&R,const int&type){
      ve.clear();
      memset(md,0,sizeof md);
      split(L,R,1,n,1);
      for(register auto t:ve){
        int*t1=data[t].buk;
        for(register int i=0;i<26;++i) {
          md[i]+=t1[i];
          t1[i]=0;
        }
      }
      register int now=0;
      if(!type) reverse(ve.begin(),ve.end());
      for(register auto t:ve){
        data[t].tag=type;
        register int*t1=data[t].buk,cnt=data[t].len;
        while(cnt>=md[now]&&cnt&&now<26) t1[now]+=md[now],cnt-=md[now],md[now]=0,++now;
        if(cnt) t1[now]+=cnt,md[now]-=cnt,cnt=0;
      }
      for(register auto t:ve) {
        if(data[t].len>1) pud(t);
        getup(t>>1);
      }
}

int main(){
      freopen("string.in","r",stdin);
      freopen("string.out","w",stdout);
      n=qr();m=qr();
      build(1,n,1);
      for(register int t=1;t<=m;++t){
        register int t2=qr(),t3=qr(),t4=qr();
        mody(t2,t3,t4);
      }
      ans(1,n,1);
      putchar('\n');
      return 0;
}

Posted by Shawazi on Tue, 08 Oct 2019 22:11:50 -0700