cf #312 E. A Simple Task (線段樹+計數排序)

題目:http://codeforces.com/contest/558/problem/E

題意:給你一個字符串s,|s|<=1e5。有q(q<50 000)次操作,有2種操作類型。①將給定區間的字符按非降序排序②將給定區間的字符按非升序排序。

分析:

計數排序:先統計區間內每種字符的個數,然後按順序將字符分配。

例如bccasabdass

a有3個 b有2個 c有2個 d有1個 s有3個

按順序分配之後就是aaabbccdsss,就已經排好序了。


現在用線段樹的每個節點保存區間內每種字符的個數,如果操作將一段區間變爲升序的話,先統計區間各字符的個數,然後按順序分配給線段樹中的合法區間,並且和以前一樣用懶惰標記方法處理區間更新。


代碼:

#include <bits/stdc++.h>
using namespace std;

#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 1E9+9;
const int maxn = 1e5+6;
char str[maxn];

struct node
{
	int num[26];
	int lazy;
}tree[maxn<<2];
int n,q;

void pushdown(int l,int r,int rt)
{
	if(tree[rt].lazy==1)  //increasing 
	{
		memset(tree[rt<<1].num,0,sizeof(int)*26);
		memset(tree[rt<<1|1].num,0,sizeof(int)*26);
		
		int m=(l+r)>>1;
		int rangeL=m-l+1;
		int cnt=0,i;
		for(i=0;i<26;i++)
		{
			if(cnt+tree[rt].num[i]>=rangeL)
			{
				tree[rt<<1].num[i]=rangeL-cnt;
				tree[rt<<1|1].num[i]=tree[rt].num[i]-(rangeL-cnt);
				i++;
				break;
			}
			cnt+=tree[rt].num[i];
			tree[rt<<1].num[i]=tree[rt].num[i];
		}
		for(;i<26;i++)
			tree[rt<<1|1].num[i]=tree[rt].num[i];
//		printf("[%d %d] [%d %d]\n",l,m,m+1,r);
//		for(int i=0;i<26;i++)
//		{
//			int t=tree[rt<<1].num[i];
//			while(t--)
//				putchar('a'+i);
//		}
//		printf("|");
//		for(int i=0;i<26;i++)
//		{
//			int t=tree[rt<<1|1].num[i];
//			while(t--)
//				putchar('a'+i);
//		}
//		printf("\n");
		tree[rt<<1].lazy=tree[rt<<1|1].lazy=1;
		tree[rt].lazy=-1;
	}
	else if(tree[rt].lazy==0)  //decreasing
	{
		memset(tree[rt<<1].num,0,sizeof(int)*26);
		memset(tree[rt<<1|1].num,0,sizeof(int)*26);
		
		int m=(l+r)>>1;
		int rangeL=m-l+1;
		int cnt=0,i;
		for(i=25;i>=0;i--)
		{
			if(cnt+tree[rt].num[i]>=rangeL)
			{
				tree[rt<<1].num[i]=rangeL-cnt;
				tree[rt<<1|1].num[i]=tree[rt].num[i]-(rangeL-cnt);
				i--;
				break;
			}
			cnt+=tree[rt].num[i];
			tree[rt<<1].num[i]=tree[rt].num[i];
		}
		for(;i>=0;i--)
			tree[rt<<1|1].num[i]=tree[rt].num[i];
		tree[rt<<1].lazy=tree[rt<<1|1].lazy=0;
		tree[rt].lazy=-1;
	}
	return ;
}

void pushup(int rt)
{
	for(int i=0;i<26;i++)
		tree[rt].num[i]=tree[rt<<1].num[i]+tree[rt<<1|1].num[i];		
}
void build(int pos,char ch,int l,int r,int rt)
{
	tree[rt].lazy=-1;
	if(l==r)
	{
		memset(tree[rt].num,0,sizeof(int)*26);
		tree[rt].num[ch-'a']++;
		return ;
	}
	int m=(l+r)>>1;
	if(pos<=m)
		build(pos,ch,lson);
	else
		build(pos,ch,rson);
	pushup(rt);
}
int buf[26];
void query(int L,int R,int l,int r,int rt)
{
	if(L<=l && r<=R)
	{
		for(int i=0;i<26;i++)
			buf[i]+=tree[rt].num[i];
		return ;
	}
	pushdown(l,r,rt);
	int m=(l+r)>>1;
	if(L<=m)
		query(L,R,lson);
	if(R>m)
		query(L,R,rson);
	pushup(rt);
}
void Q(int L,int R)
{
	memset(buf,0,sizeof(buf));
	query(L,R,1,n,1);
}
void update1(int L,int R,int l,int r,int rt)
{
	if(L<=l && r<=R)
	{
		int range=r-l+1,cnt=0;
		memset(tree[rt].num,0,sizeof(int)*26);
		for(int i=0;i<26;i++)
		{
			if(cnt+buf[i]>=range)
			{
				tree[rt].num[i]+=range-cnt;
				buf[i]-=(range-cnt);
				break;
			}
			tree[rt].num[i]=buf[i];
			cnt+=buf[i];
			buf[i]=0;
		}
		tree[rt].lazy=1;
		return ;
	}
	pushdown(l,r,rt);
	int m=(l+r)>>1;
	if(L<=m)
		update1(L,R,lson);
	if(R>m)
		update1(L,R,rson);
	pushup(rt);
}

void update0(int L,int R,int l,int r,int rt)
{
	if(L<=l && r<=R)
	{
		int range=r-l+1,cnt=0;
		memset(tree[rt].num,0,sizeof(int)*26);
		for(int i=25;i>=0;i--)
		{
			if(cnt+buf[i]>=range)
			{
				tree[rt].num[i]+=range-cnt;
				buf[i]-=(range-cnt);
				break;
			}
			tree[rt].num[i]=buf[i];
			cnt+=buf[i];
			buf[i]=0;
		}
		tree[rt].lazy=0;
		return ;
	}
	pushdown(l,r,rt);
	int m=(l+r)>>1;
	if(L<=m)
		update0(L,R,lson);
	if(R>m)
		update0(L,R,rson);
	pushup(rt);
}

char getChar(int pos,int l,int r,int rt)
{
	if(l==r)
	{
		for(int i=0;i<26;i++)
			if(tree[rt].num[i])
				return 'a'+i;
		return '*';
	}
	pushdown(l,r,rt);
	int m=(l+r)>>1;
	if(pos<=m)
		return	getChar(pos,lson);
	else
		return getChar(pos,rson);
	pushup(rt);
}


int main()
{
	int i,j,k;
	scanf("%d%d",&n,&q);
	scanf("%s",str);
	for(int i=0;str[i];i++)
		build(i+1,str[i],1,n,1);
//	for(int i=0;str[i];i++)
//	{
//		putchar(getChar(i+1,1,n,1));
//	}
//	printf("\n");
	while(q--)
	{
		scanf("%d%d%d",&i,&j,&k);
		Q(i,j);
		if(k==1)
			update1(i,j,1,n,1);
		else
			update0(i,j,1,n,1);
//		for(int i=0;str[i];i++)
//		{
//			putchar(getChar(i+1,1,n,1));
//		}
//		printf("\n");
//		int x;
//		while(cin>>x)
//		{
//			putchar(getChar(x,1,n,1));
//		}
	}
	for(int i=1;i<=n;i++)
		putchar(getChar(i,1,n,1));
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章