Codeforces Round #337 (Div. 2) E. Alphabet Permutations (線段樹lazy 或 set)

大致題意:

一個2e5的字符串STR,最多包含K個字符(K < 10) , 有Q個操作(<2e4) 。

1. 把字符串[L, R]的字符修改成x

2. 給一個K個字符的某個排列s,詢問最少重複次數的s連接而成的長串的子序列包含STR

思路1:

因爲要修改STR,所以要對STR進行處理,然後要在logn以下的複雜度完成查詢操作。

可以注意到最少重複的次數就是STR中相鄰的兩個字符(ch1, ch2) 在排列s中的位置是ch2在ch1之前,ch2和ch1必然是有兩個s串組成。所以可以維護STR相鄰字符的對數。用cnt[ch1][ch2]矩陣維護相鄰字符ch1ch2的對數。答案就是len(STR) - 相鄰對數

由於有修改操作,必須用線段樹維護,所以修改的複雜度在O(Qlogn*K*K),查詢的複雜度是O(K*K).問題解決


思路2:

同樣是維護cnt矩陣,但不用線段樹維護,用set維護(http://codeforces.com/contest/610/submission/15053499), 由代碼可以看出,當修改某一段字符的時候,暴力維護,然後[L, R]字符已經相同,沒有相鄰對數了,所以刪去set中的[L, R],然後插入兩個邊界的相鄰情況。

這樣均攤複雜度是:每次修改操作最多在set裏增加2個值,所以整個修改過程最多增加O(n) , 刪除的個數不會多於增加的值個數,也是O(n).

所以總複雜度是O(Q * K * K + n) 比 方法一的O(Q * K * K + Qlogn* K * K) 優了logn * K * K級別。


方法一代碼:(佔用內存比較多,所以用了2倍空間的線段樹)

//#pragma comment(linker, "/STACK:1024000000,1024000000")  
#include <iostream>  
#include <cstring>  
#include <cmath>  
#include <queue>  
#include <stack>  
#include <map>  
#include <set>  
#include <string>  
#include <vector>  
#include <cstdio>  
#include <ctime>  
#include <bitset>  
#include <algorithm>  
#define SZ(x) ((int)(x).size())  
#define ALL(v) (v).begin(), (v).end()  
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)  
#define reveach(i, v) for (__typeof((v).rbegin()) i = (v).rbegin(); i != (v).rend(); ++ i)  
#define REP(i,n) for ( int i=1; i<=int(n); i++ )  
#define rep(i,n) for ( int i=0; i< int(n); i++ )  
using namespace std;  
typedef long long ll;  
#define X first  
#define Y second  
#define PB push_back  
#define MP make_pair  
typedef long double ld;
typedef pair<int, int> pii;  
  
template <class T>  
inline bool RD(T &ret) {  
        char c; int sgn;  
        if (c = getchar(), c == EOF) return 0;  
        while (c != '-' && (c<'0' || c>'9')) c = getchar();  
        sgn = (c == '-') ? -1 : 1 , ret = (c == '-') ? 0 : (c - '0');  
        while (c = getchar(), c >= '0'&&c <= '9') ret = ret * 10 + (c - '0');  
        ret *= sgn;  
        return 1;  
}  
template <class T>  
inline void PT(T x) {  
        if (x < 0) putchar('-') ,x = -x;  
        if (x > 9) PT(x / 10);  
        putchar(x % 10 + '0');  
}

const int N = 2e5 + 100;

char s[N];
int n, Q, K;

struct node {
	int cnt[10][10];
	int lv, rv, lazy;
};

struct SegmentTree {
    inline int get_id(int l,int r) {
		return (l + r) | (l != r);
	}
	
	node a[2 * N];

	void up(int l, int r) {
		int mid = (l + r) >> 1;
		int rt = get_id(l, r), ls = get_id(l, mid), rs = get_id(mid + 1, r);
		rep(i, K) 
			rep(j, K) a[rt].cnt[i][j] = a[ls].cnt[i][j] + a[rs].cnt[i][j];
		a[rt].cnt[a[ls].rv][a[rs].lv] ++;
		a[rt].lv = a[ls].lv;
		a[rt].rv = a[rs].rv;
	}

	void down(int l, int r) {
		int mid = (l + r) >> 1;
		int rt = get_id(l, r), ls = get_id(l, mid), rs = get_id(mid + 1, r);
		if(a[rt].lazy == -1) return ;
		memset(a[ls].cnt, 0, sizeof(a[ls].cnt));
		memset(a[rs].cnt, 0, sizeof(a[rs].cnt));
		a[ls].lazy = a[ls].lv = a[ls].rv = a[rs].lazy = a[rs].lv = a[rs].rv = a[rt].lazy;
		a[rt].lazy = -1;
	}

	void build(int l, int r) {
		int rt = get_id(l, r);
		a[rt].lazy = -1;
		if(l == r) {
			a[rt].lv = a[rt].rv = s[l] - 'a';
			return ;
		}
		int mid = (l + r) >> 1;
		build(l, mid);
		build(mid + 1, r);
		up(l, r);
	}

	void update(int L, int R, int val, int l, int r) {
		int rt = get_id(l, r);
		int mid = (l + r) >> 1;
		if( L <= l && r <= R) {
			memset(a[rt].cnt, 0, sizeof(a[rt].cnt));
			a[rt].lazy = a[rt].lv = a[rt].rv = val;
			return ;
		}
		down(l, r);
		if(L <= mid) update(L, R, val, l, mid);
		if(R > mid) update(L, R, val, mid + 1, r);
		up(l, r);
	}

	void debug(int pos, int l, int r) {
		int rt = get_id(l, r);
		if( l == r ) {
			printf("(%c %c)\n", a[rt].lv + 'a', a[rt].rv + 'a');
			return ;
		}
		down(l, r);
		int mid = (l + r) >> 1;
		if(pos <= mid) debug(pos, l, mid);
		else debug(pos, mid + 1, r);
	}
}A;


int main() {
	cin >> n >> Q >> K;
	scanf("%s", s + 1);
	A.build(1, n);
	REP(i, Q) {
		int op;
		RD(op);
		if(op == 1) {
			int l, r;
			char val[5];
			RD(l), RD(r);
			scanf("%s", val);
			A.update(l, r, val[0] - 'a', 1, n);
		} else {
			scanf("%s", s);
			int ans = n;
			for(int i = 0; s[i]; i ++)
				for(int j = i + 1; s[j]; j ++) 
					ans -= A.a[A.get_id(1, n)].cnt[s[i] - 'a'][s[j] - 'a'];
			printf("%d\n", ans);
		}
	//	REP(i, n) A.debug(i, 1, n);
	}
}


方法二代碼:http://codeforces.com/contest/610/submission/15053499


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 functiond(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 strings, 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 li to 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).

Sample test(s)
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.



發佈了308 篇原創文章 · 獲贊 11 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章