[CF558E]A Simple Task
阿新 • • 發佈:2017-10-03
scanf 輸出 src n+1 urn () size true pos
題意:對字符串進行多次區間排序(可升可降),最後輸出結果
極其暴力~
對每個字符建一棵線段樹,每次排序$[l,r]$就是將$26$個字母的線段樹清空$[l,r]$然後依次把相應區間賦值為$1$,最後統計答案
orz洪雲神犇,真不知道這到底是怎麽跑出來的
#include<stdio.h> int sum[26][400000],laz[26][400000]; void pushdown(int c,int x,int ln,int rn){ if(laz[c][x]){ laz[c][x<<1]=laz[c][x<<1|1]=laz[c][x]; sum[c][x<<1]=ln*(laz[c][x]-1); sum[c][x<<1|1]=rn*(laz[c][x]-1); laz[c][x]=0; } } void pushup(int c,int x){ sum[c][x]=sum[c][x<<1]+sum[c][x<<1|1]; } void modify(int c,int L,int R,int v,int l,int r,int x){ if(L<=l&&r<=R){ laz[c][x]=v+1; sum[c][x]=v*(r-l+1); return; } int mid=(l+r)>>1; pushdown(c,x,mid-l+1,r-mid); if(L<=mid)modify(c,L,R,v,l,mid,x<<1); if(mid<R)modify(c,L,R,v,mid+1,r,x<<1|1); pushup(c,x); } int query(int c,int L,int R,int l,int r,int x){ if(L<=l&&r<=R)return sum[c][x]; int mid=(l+r)>>1,ans=0; pushdown(c,x,mid-l+1,r-mid); if(L<=mid)ans+=query(c,L,R,l,mid,x<<1); if(mid<R)ans+=query(c,L,R,mid+1,r,x<<1|1); return ans; } char s[100010]; int main(){ int n,m,i,l,r,op,pos,len; scanf("%d%d%s",&n,&m,s+1); for(i=1;i<=n;i++)modify(s[i]-‘a‘,i,i,1,1,n,1); while(m--){ scanf("%d%d%d",&l,&r,&op); if(op==1){ pos=l; for(i=0;i<26;i++){ len=query(i,l,r,1,n,1); if(len){ modify(i,l,r,0,1,n,1); modify(i,pos,pos+len-1,1,1,n,1); pos+=len; } } }else{ pos=r; for(i=0;i<26;i++){ len=query(i,l,r,1,n,1); if(len){ modify(i,l,r,0,1,n,1); modify(i,pos-len+1,pos,1,1,n,1); pos-=len; } } } } for(i=1;i<=n;i++){ for(op=0;op<26;op++){ if(query(op,i,i,1,n,1)){ putchar(op+‘a‘); break; } } } }
[CF558E]A Simple Task