1. 程式人生 > >[CF558E]A Simple Task

[CF558E]A Simple Task

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