zoukankan      html  css  js  c++  java
  • CF1098F Ж-function [后缀自动机+扫描线]

    这题好仙啊,不会。后面看懂了再来填坑吧。

    // by Isaunoya
    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    const int maxn = 4e5 + 58;
    using ll = long long;
    struct smt {
    	int n, size, rt;
    	int ls[maxn << 1], rs[maxn << 1];
    	ll tag[maxn << 1];
    	ll cnt[maxn << 1], sum[maxn << 1];
    
    	void init(int sz, int *tmp) {
    		size = rt = 0, n = sz, bld(rt, 1, n, tmp);
    	}
    
    	void up(int p) {
    		sum[p] = sum[ls[p]] + sum[rs[p]];
    	}
    	
    	void bld(int &p, int l, int r, int *tmp) {
    		p = ++ size;
    		if(l == r) {
    			cnt[p] = tmp[l];
    			return;
    		}
    		int mid = l + r >> 1;
    		bld(ls[p], l, mid, tmp);
    		bld(rs[p], mid + 1, r, tmp);
    		cnt[p] = cnt[ls[p]] + cnt[rs[p]];
    	}
    
    	void down(int p) {
    		if(tag[p]) {
    			tag[ls[p]] += tag[p], sum[ls[p]] += tag[p] * cnt[ls[p]];
    			tag[rs[p]] += tag[p], sum[rs[p]] += tag[p] * cnt[rs[p]];
    			tag[p] = 0;
    		}
    	}
    	void mdf(int p, int ql, int qr, int l, int r, int v) {
    		if(ql <= l && r <= qr) {
    			tag[p] += v, sum[p] += v * cnt[p];
    			return;
    		}
    		down(p);
    		int mid = l + r >> 1;
    		if(ql <= mid) mdf(ls[p], ql, qr, l, mid, v);
    		if(qr > mid) mdf(rs[p], ql, qr, mid + 1, r, v);
    		up(p);
    	}
    	void mdf(int ql, int qr, int v) {
    		mdf(rt, ql, qr, 1, n, v);
    	}
    	ll qry(int p, int ql, int qr, int l, int r) {
    		if(ql <= l && r <= qr) {
    			return sum[p];
    		}
    		down(p);
    		int mid = l + r >> 1;
    		ll ans = 0;
    		if(ql <= mid) ans += qry(ls[p], ql, qr, l, mid);
    		if(qr > mid) ans += qry(rs[p], ql, qr, mid + 1, r);
    		return ans;
    	}
    	int qry(int ql, int qr) {
    		return qry(rt, ql, qr, 1, n);
    	}
    	ll qry(int p, int x, int l, int r) {
    		if(l == r) {
    			return tag[p];
    		}
    		down(p);
    		int mid = l + r >> 1;
    		if(x <= mid) return qry(ls[p], x, l, mid);
    		else return qry(rs[p], x, mid + 1, r);
    	}
    	ll qry(int x) { return qry(rt, x, 1, n); }
    } smt;
    
    struct BIT {
    	int n;
    	vector <ll> c;
    	void init(int _n) {
    		n = _n + 1;
    		c.resize(n + 1);
    	}
    	int low(int x) {
    		return x & -x;
    	}
    	void u(int x, int y) {
    		for(; x <= n; x += low(x)) c[x] += y;
    	}
    	ll q(int x) {
    		ll ans = 0;
    		for(; x; x ^= low(x)) ans += c[x];
    		return ans;
    	}
    	ll qry(int x) { return q(x); }
    	ll qry(int l, int r) {
    		if(l > r)
    			return 0;
    		return q(r) - q(l - 1);
    	}
    } al[2], pt[2];
    
    int pos[maxn], rev[maxn];
    struct suffixautomaton {
    	int ch[maxn][26], fa[maxn], len[maxn];
    	int las, cnt;
    	suffixautomaton() { las = cnt = 1; }
    
    	void ins(int c, int id) {
    		int p = las, np = las = ++cnt;
    		pos[np] = id;
    		len[np] = len[p] + 1;
    		for(; p && !ch[p][c]; p = fa[p]) ch[p][c] = np;
    		if(!p) {
    			fa[np] = 1;
    		} else {
    			int q = ch[p][c];
    			if(len[q] == len[p] + 1) {
    				fa[np] = q;
    			} else {
    				int nq = ++cnt;
    				len[nq] = len[p] + 1;
    				fa[nq] = fa[q], fa[q] = fa[np] = nq;
    				memcpy(ch[nq], ch[q], sizeof(ch[q]));
    				for(; p && ch[p][c] == q; p = fa[p]) ch[p][c] = nq;
    			}
    		}
    	}
    } sam;
    
    int n, t, len;
    char s[maxn];
    int dep[maxn], f[maxn][22];
    vector <int> g[maxn];
    int ql[maxn], qr[maxn], from[maxn];
    
    int sz[maxn], fa[maxn], son[maxn];
    void dfs(int u) {
    	sz[u] = 1;
    	for(int v: g[u]) {
    		if(v ^ fa[u]) {
    			fa[v] = u, dfs(v), sz[u] += sz[v];
    			if(sz[v] > sz[son[u]]) son[u] = v;
    		}
    	}
    }
    
    int top[maxn], dfn[maxn];
    //dfo[maxn];
    int idx = 0;
    void dfs(int u, int t) {
    	top[u] = t, dfn[u] = ++ idx;
    	if(son[u]) dfs(son[u], t);
    	for(int v: g[u])
    		if(!top[v]) dfs(v, v);
    //	dfo[u] = idx;
    }
    
    ll ans[maxn];
    
    void Scanninglinefir() {
    	static int tmp[maxn];
    	for(int i = 1 ; i <= n ; i ++) {
    		tmp[dfn[i]] = dep[i] - dep[fa[i]];
    	}
    	smt.init(n, tmp);
    	static vector <pair<pair<int, int>, int>> q[maxn];
    	for(int i = 1 ; i <= t ; i ++) {
    		q[ql[i]].push_back(make_pair(make_pair(from[i], qr[i] - ql[i] + 1), i));
    	}
    	for(int i = 1 ; i <= len ; i ++) {
    		auto query = [&](pair<int, int> x) {
    			ll ans = 1ll * (x.second - dep[fa[x.first]]) * smt.qry(dfn[x.first]);
    			int pos = fa[x.first];
    			while(pos) {
    				ans += smt.qry(dfn[top[pos]], dfn[pos]), pos = fa[top[pos]];
    			}
    			return ans;
    		};
    		for(auto x : q[i]) {
    			ans[x.second] -= query(x.first);
    		}
    		int pos = rev[i];
    		while(pos) {
    			smt.mdf(dfn[top[pos]], dfn[pos], 1), pos = fa[top[pos]];
    		}
    	}
    }
    
    void Scanninglinesec() {
    	static vector <pair<int, int>> mdf[maxn];
    	static vector <pair<pair<int, int>, int>> qry[maxn];
    	for(int i = 1 ; i <= len ; i ++) {
    		int pos = rev[i];
    		while(pos) {
    			mdf[top[pos]].emplace_back(dep[pos], i), pos = fa[top[pos]];
    		}
    	}
    	for(int i = 1 ; i <= t ; i ++) {
    		int pos = from[i];
    		while(pos) {
    			if(pos == from[i]) {
    				qry[top[pos]].emplace_back(make_pair(qr[i] - ql[i] + 1, qr[i] + 1), i);
    			} else {
    				qry[top[pos]].emplace_back(make_pair(dep[pos], qr[i] + 1), i);
    			}
    			pos = fa[top[pos]];
    		}
    	}
    	al[0].init(len * 2 + 2), al[1].init(len * 2 + 2);
    	pt[0].init(len * 2 + 2), pt[1].init(len * 2 + 2);
    	for(int i = 1 ; i <= n ; i ++) {
    		if(top[i] != i) { continue; }
    		int st = dep[fa[i]] + 1;
    		sort(mdf[i].begin(), mdf[i].end()), reverse(mdf[i].begin(), mdf[i].end());
    		sort(qry[i].begin(), qry[i].end()), reverse(qry[i].begin(), qry[i].end());
    		vector <pair<int, int>> bak = mdf[i];
    		for(auto x: bak) {
    			al[0].u(x.second, x.second), al[1].u(x.second, 1);
    		}
    		while(!mdf[i].empty() || !qry[i].empty()) {
    			if(mdf[i].empty() || (!qry[i].empty() && qry[i].back().first.first <= mdf[i].back().first)) {
    				pair <int, int> x = qry[i].back().first;
    				int pos = qry[i].back().second;
    				ans[pos] += 1ll * pt[1].qry(x.second) * x.second + pt[0].qry(x.second);
    				int tmp = x.second - x.first;
    				if(tmp >= 1) {
    					ans[pos] += al[1].qry(1, tmp) * (x.first - st + 1);
    				}
    				tmp = max(tmp, 0ll);
    				ans[pos] += 1ll * al[1].qry(tmp + 1, x.second - st) * (x.second - st + 1) - al[0].qry(tmp + 1, x.second - st);
    				qry[i].pop_back();
    			} else {
    				pair <int, int> x = mdf[i].back();
    				al[0].u(x.second, -x.second), al[1].u(x.second, -1);
    				pt[0].u(st + x.second, -(st + x.second - 1));
    				pt[0].u(x.first + x.second + 1, st + x.second - 1 + x.first - st + 1);
    				pt[1].u(st + x.second, 1), pt[1].u(x.first + x.second + 1, -1);
    				mdf[i].pop_back();
    			}
    		}
    		for(auto x: bak) {
    			pt[0].u(st + x.second, st + x.second - 1);
    			pt[0].u(x.first + x.second + 1, -(st + x.second - 1 + x.first - st + 1));
    			pt[1].u(st + x.second, -1), pt[1].u(x.first + x.second + 1, 1);
    		}
    	}	
    }
    
    signed main() {
    #ifdef LOCAL
    	freopen("testdata.in", "r", stdin);
    #endif
    	scanf("%s", s + 1);
    	len = strlen(s + 1);
    	for(int i = len ; i ; i --) {
    		sam.ins(s[i] - 'a', i);
    	}
    	n = sam.cnt;
    	for(int i = 1 ; i <= n ; i ++) {
    		dep[i] = sam.len[i];
    		if(pos[i]) rev[pos[i]] = i;
    	}
    	for(int i = 2 ; i <= n ; i ++) {
    		g[sam.fa[i]].push_back(i);
    	}
    	dfs(1),	dfs(1, 1);
    	scanf("%lld", &t);
    	for(int i = 1 ; i <= t ; i ++) {
    		int l, r; scanf("%lld %lld", &l, &r);
    		ql[i] = l, qr[i] = r;
    	}
    	for(int i = 1 ; i <= n ; i ++) {
    		f[i][0] = sam.fa[i];
    	}
    	for(int j = 1 ; j <= 20 ; j ++)
    		for(int i = 1 ; i <= n ; i ++) f[i][j] = f[f[i][j - 1]][j - 1];
    	for(int i = 1 ; i <= t ; i ++) {
    		int l = ql[i], r = qr[i], goal = r - l + 1, p = rev[l];
    		for(int j = 20; ~j; -- j) if(f[p][j] && dep[f[p][j]] >= goal) p = f[p][j];
    		from[i] = p;
    	}
    	Scanninglinefir(), Scanninglinesec();
    	for(int i = 1 ; i <= t ; i ++) printf("%lld
    ", ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    第十五章:Spring Boot 与 开发热部署
    第一章:(1)分布式基础理论
    第一章:(4)Dubbo 案例 HelloWorld
    第一章:(2)Dubbo核心概念
    第十四章:(3)Spring Boot 与 分布式 之 SpringCloud
    web安全测试AppScan扫描工具
    Cheatsheet: 2013 02.01 ~ 02.15
    Cheatsheet: 2013 04.17 ~ 04.30
    Cheatsheet: 2013 02.16 ~ 02.28
    Cheatsheet: 2013 01.21 ~ 01.31
  • 原文地址:https://www.cnblogs.com/Isaunoya/p/12818907.html
Copyright © 2011-2022 走看看