标签:sum down main 字符 div stdio.h clu .com 技术分享
题意:对字符串进行多次区间排序(可升可降),最后输出结果
极其暴力~
对每个字符建一棵线段树,每次排序$[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;
}
}
}
}
标签:sum down main 字符 div stdio.h clu .com 技术分享
原文地址:http://www.cnblogs.com/jefflyy/p/7624422.html