codeforces #337 E. Alphabet Permutations (线段树区间合并)

题目:http://codeforces.com/contest/610/problem/E

题意:给定一个长度为n(n<200 000)的字符串s,有两种指令:Ⅰ.将区间[L,R]内的字符变为ch,Ⅱ.给定长度为k(1<=k<=10)的字符串排列t,向s串中添加字符,使得s以t为模式循环,求最少的循环次数。最多20000条指令。

E. Alphabet Permutations
time limit per test
1 second
memory limit per test
512 megabytes
input
standard input
output
standard output

You are given a string s of length n, consisting of first k lowercase English letters.

We define a c-repeat of some string q as a string, consisting of c copies of the string q. For example, string "acbacbacbacb" is a 4-repeat of the string "acb".

Let's say that string a contains string b as a subsequence, if string b can be obtained from a by erasing some symbols.

Let p be a string that represents some permutation of the first k lowercase English letters. We define function d(p) as the smallest integer such that a d(p)-repeat of the string p contains string s as a subsequence.

There are m operations of one of two types that can be applied to string s:

  1. Replace all characters at positions from li to ri by a character ci.
  2. For the given p, that is a permutation of first k lowercase English letters, find the value of function d(p).

All operations are performed sequentially, in the order they appear in the input. Your task is to determine the values of function d(p) for all operations of the second type.

Input

The first line contains three positive integers nm and k (1 ≤ n ≤ 200 000, 1 ≤ m ≤ 20000, 1 ≤ k ≤ 10) — the length of the string s, the number of operations and the size of the alphabet respectively. The second line contains the string s itself.

Each of the following lines m contains a description of some operation:

  1. Operation of the first type starts with 1 followed by a triple liri and ci, that denotes replacement of all characters at positions from lito ri by character ci (1 ≤ li ≤ ri ≤ nci is one of the first k lowercase English letters).
  2. Operation of the second type starts with 2 followed by a permutation of the first k lowercase English letters.
Output

For each query of the second type the value of function d(p).

Examples
input
7 4 3
abacaba
1 3 5 b
2 abc
1 4 4 c
2 cba
output
6
5
Note

After the first operation the string s will be abbbbba.

In the second operation the answer is 6-repeat of abcABcaBcaBcaBcaBcAbc.

After the third operation the string s will be abbcbba.

In the fourth operation the answer is 5-repeat of cbacbAcBacBaCBacBA.

Uppercase letters means the occurrences of symbols from the string s.


分析:

解法十分暴力,建一棵线段树,线段树中的每一个节点保存一个k*k的数组,记录ch1和ch2相连的次数。然后区间合并就行了。。。

代码:

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

typedef long long LL;
typedef unsigned long long ULL;
const LL INF = 1e9+7;
const LL MINT = ~0u>>1;

const int maxn = 200006<<2;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

struct node
{
	static const int sz = 10;
	
	int matrix[sz][sz];
	char lazy;
	char lchar,rchar;	
}tree[maxn];

int n,m,k;
char str[maxn],temp[maxn];

void pushdown(int rt)
{
	if(tree[rt].lazy!='#')
	{
		tree[rt<<1].lazy=tree[rt<<1|1].lazy=tree[rt].lazy;
		
		memset(tree[rt<<1].matrix,0,sizeof(tree[rt<<1].matrix));
		memset(tree[rt<<1|1].matrix,0,sizeof(tree[rt<<1|1].matrix));
		
		tree[rt<<1].lchar=tree[rt<<1].rchar=tree[rt].lazy;
		tree[rt<<1|1].lchar=tree[rt<<1|1].rchar=tree[rt].lazy;
		
		tree[rt].lazy='#';
	}
}
void pushup(int rt)
{
	for(int i=0;i<k;i++)
		for(int j=0;j<k;j++)
			tree[rt].matrix[i][j]=tree[rt<<1].matrix[i][j]+tree[rt<<1|1].matrix[i][j];
	int index1=tree[rt<<1].rchar-'a';
	int index2=tree[rt<<1|1].lchar-'a';
	++tree[rt].matrix[index1][index2];
	
	tree[rt].lchar=tree[rt<<1].lchar;
	tree[rt].rchar=tree[rt<<1|1].rchar;
}
void build(int l,int r,int rt)
{
	tree[rt].lazy='#';
	if(l==r)
	{
		memset(tree[rt].matrix,0,sizeof(tree[rt].matrix));
		tree[rt].lchar=tree[rt].rchar=str[r];
		return ;
	}
	int m=(l+r)>>1;
	build(lson);
	build(rson);
	pushup(rt);
}
void update(int L,int R,char ch,int l,int r,int rt)
{
	if(L<=l && r<=R)
	{
		tree[rt].lazy=ch;
		tree[rt].lchar=tree[rt].rchar=ch;
		memset(tree[rt].matrix,0,sizeof(tree[rt].matrix));
		return ;
	}
	pushdown(rt);
	int m=(l+r)>>1;
	if(L<=m)
		update(L,R,ch,lson);
	if(R>m)
		update(L,R,ch,rson);
	pushup(rt);
}

void solve()
{
	int ans=n;
	for(int i=0;i<k;i++)
		for(int j=i+1;j<k;j++)
		{
			int index1=temp[i]-'a';
			int index2=temp[j]-'a';
			ans-=tree[1].matrix[index1][index2];
		}
	printf("%d\n",ans);
}

int main()
{
	scanf("%d%d%d",&n,&m,&k);
	scanf("%s",str+1);
	build(1,n,1);
	while(m--)
	{
		int tp;
		scanf("%d",&tp);
		if(tp==1)
		{
			int L,R;
			char ch[2];
			scanf("%d%d%s",&L,&R,ch);
			update(L,R,ch[0],1,n,1);
		}
		else
		{
			scanf("%s",temp);
			solve();
		}
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值