求助 TLE on #12
查看原帖
求助 TLE on #12
488052
FLY_lai楼主2024/8/12 20:36
#include <bits/stdc++.h>

using namespace std;
typedef long long ll; 
const int N = 6e5 + 5;

struct SegmentTree {
	int sz;
	vector<int> val;
	int ide = 0x3f3f3f3f;
	
	SegmentTree(){}
	SegmentTree(int n) {
		for (sz = 1; sz < n; sz *= 2);
		val.assign(2 * sz, ide);
	}
	void pushup(int x) {
		val[x] = min(val[x * 2], val[x * 2 + 1]);
	}
	void mdf(int x, int lx, int rx, int p, int v) {
		if (lx + 1 == rx) {
			val[x] = v;
			return ;
		}
		int m = (lx + rx) / 2;
		if (p < m)
			mdf(x * 2, lx, m, p, v);
		else
			mdf(x * 2 + 1, m, rx, p, v);
		pushup(x);
	}
	int qry(int x, int lx, int rx, int l, int r) {
		if (l <= lx && rx <= r)
			return val[x];
		if (l >= rx || lx >= r)
			return ide;
		int m = (lx + rx) / 2;
		return min(qry(x * 2, lx, m, l, r), qry(x * 2 + 1, m, rx, l, r));
	}
} st;

ll n;
ll lst = 0, lstb = 0; //上一次的答案,上一次的border总和 
map<ll, ll> mp; //mp[i]表示可疑度为i的border个数 

char ch[N];
ll w[N];
ll nxt[N];
ll dif[N]; //dif[i]表示i在nxt树上第一个与它下一个字符对应不同的 

int main() {
	
//	freopen("1.in", "r", stdin);
//	 freopen("1.out", "w", stdout);
	cin >> n;
	st = SegmentTree(n);
	
	nxt[0] = 0;
	dif[0] = 0;
	
	int MMM = (1 << 30) - 1;
	for (int i = 1; i <= n; i++) {
		ll now = lstb;
		while (true) {
			ch[i] = getchar();
			if (ch[i] != ' ' && ch[i] != '\n')
				break;
		}
		scanf("%lld", &w[i]);
		ch[i] = (lst + ch[i] - 'a') % 26 + 'a';
		w[i] = w[i] ^ (lst & MMM);
//		printf("\"%c, %d\"\n", ch[i], w[i]);
		
		st.mdf(1, 1, st.sz + 1, i, w[i]);
//		cout << "w[2,3]=" << st.qry(1, 1, st.sz + 1, 2, 4) << endl;
		
		if (i > 1) {
			int cur = nxt[i - 1];
			while (cur > 0 && ch[cur + 1] != ch[i])
				cur = nxt[cur];
			if (ch[cur + 1] == ch[i])
				nxt[i] = cur + 1;
		}
//		cout << nxt[i] << endl;
		
		//更新dif[nxt[i]] 
		if (ch[nxt[i] + 1] == ch[nxt[nxt[i]] + 1])
			dif[nxt[i]] = dif[nxt[nxt[i]]];
		else
			dif[nxt[i]] = nxt[nxt[i]];
		
		//1 删除
		if (i > 1) {
//			cout << "删除:\n";
			int pos = nxt[i - 1];
			while (true) {
				if (pos == 0)
					break;
				
				if (ch[pos + 1] != ch[i]) {
					int sus = st.qry(1, 1, st.sz + 1, i - pos, i);
					mp[sus]--;
					now -= sus;
//					printf("[%d,%d):", i - pos, i);
//					cout << ch[pos + 1] << ' ' << ch[i] << endl;
//					cout << pos << ',' << sus << endl;
					pos = nxt[pos]; 
				}
				else
					pos = dif[pos];
			} 
		}
		
		//2 修改
		if (mp.begin() != mp.end()) {
//			cout << "修改:\n";
			auto pt = mp.end();
			pt--;
			while (true) {
				if ((*pt).first <= w[i])
					break;
//				printf("(%d,%d)\n", (*pt).first, (*pt).second);
				now -= 1ll * (*pt).first * (*pt).second;
				now += 1ll * (*pt).second * w[i];
				mp[w[i]] += (*pt).second;
				mp[(*pt).first] = 0; 
				if (pt == mp.begin())
					break;
				pt--;
			}
		}
		
		//3 添加
		if (ch[i] == ch[1]) {
//			cout << "添加:\n";
			mp[w[i]]++;
			now += w[i];
//			printf("add:%d\n", w[i]);
		}
//		cout << "答案:";
		printf("%lld\n", now + lst);
		lst += now;
		lstb = now;
//		for (auto i: mp)
//			printf("(%d,%d)", i.first, i.second);
//		cout << endl;
//		cout << endl;
	}
	return 0;
}
/*
4
s 838220732
e 269827753
h 1020606579
s 812800242
*/
2024/8/12 20:36
加载中...