• Bzoj4199:[NOI2015]品酒大会


    题面

    Bzoj4199

    Sol

    后缀数组
    显然的暴力就是求(LCP)+差分
    (40)

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(3e5 + 5);
    
    IL int Input(){
        RG int x = 0, z = 1; RG char c = getchar();
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    int a[_], n, s[_], rk[_], sa[_], height[_], tmp[_], t[_];
    ll ans1[_], ans2[_];
    int st[20][_], lg[_];
    char ss[_];
    
    IL int Cmp(RG int i, RG int j, RG int k){
        return tmp[i] == tmp[j] && i + k <= n && j + k <= n && tmp[i + k] == tmp[j + k];
    }
    
    IL void Suffix_Sort(){
        RG int m = 26;
        for(RG int i = 1; i <= n; ++i) ++t[rk[i] = s[i]];
        for(RG int i = 1; i <= m; ++i) t[i] += t[i - 1];
        for(RG int i = n; i; --i) sa[t[rk[i]]--] = i;
        for(RG int k = 1; k <= n; k <<= 1){
            RG int l = 0;
            for(RG int i = n - k + 1; i <= n; ++i) tmp[++l] = i;
            for(RG int i = 1; i <= n; ++i) if(sa[i] > k) tmp[++l] = sa[i] - k;
            for(RG int i = 0; i <= m; ++i) t[i] = 0;
            for(RG int i = 1; i <= n; ++i) ++t[rk[tmp[i]]];
            for(RG int i = 1; i <= m; ++i) t[i] += t[i - 1];
            for(RG int i = n; i; --i) sa[t[rk[tmp[i]]]--] = tmp[i];
            swap(tmp, rk), rk[sa[1]] = l = 1;
            for(RG int i = 2; i <= n; ++i) rk[sa[i]] = Cmp(sa[i - 1], sa[i], k) ? l : ++l;
            if(l >= n) break;
            m = l;
        }
        for(RG int i = 1, h = 0; i <= n; ++i){
            if(h) --h;
            while(s[i + h] == s[sa[rk[i] - 1] + h]) ++h;
            height[rk[i]] = h;
        }
    }
    
    IL void ST_Prepare(){
        for(RG int i = 2; i <= n; ++i) lg[i] = lg[i >> 1] + 1;
        for(RG int i = 1; i <= n; ++i) st[0][i] = height[i];
        for(RG int i = 1; i <= lg[n]; ++i)
            for(RG int j = 1; j + (1 << i) - 1 <= n; ++j)
                st[i][j] = min(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);
    }
    
    IL int LCP(RG int x, RG int y){
        x = rk[x], y = rk[y];
        if(x > y) swap(x, y); ++x;
        RG int len = y - x + 1;
        return min(st[lg[len]][x], st[lg[len]][y - (1 << lg[len]) + 1]);
    }
    
    int main(RG int argc, RG char* argv[]){
        Fill(ans2, -127), n = Input(), scanf(" %s", ss + 1);
        for(RG int i = 1; i <= n; ++i) s[i] = ss[i] - 'a' + 1, a[i] = Input();
        Suffix_Sort(), ST_Prepare();
        for(RG int i = 1; i < n; ++i)
            for(RG int j = i + 1; j <= n; ++j){
                RG int lcp = LCP(i, j);
                ++ans1[0], --ans1[lcp + 1];
                ans2[lcp] = max(ans2[lcp], 1LL * a[i] * a[j]);
            }
        for(RG int i = 0; i < n; ++i) ans1[i] += ans1[i - 1];
        for(RG int i = n - 1; ~i; --i) ans2[i] = max(ans2[i], ans2[i + 1]);
        for(RG int i = 0; i < n; ++i) printf("%lld %lld
    ", ans1[i], ans2[i] == ans2[n] ? 0 : ans2[i]);
        return 0;
    }
    
    

    正解,把(height)从大到小排序
    每次合并(height)两边的集合,因为从大到小,所以两边集合的(LCP)一定就是这个(height),因为有负数权值,维护集合的最大值,最小值组合

    # include <bits/stdc++.h>
    # define RG register
    # define IL inline
    # define Fill(a, b) memset(a, b, sizeof(a))
    using namespace std;
    typedef long long ll;
    const int _(3e5 + 5);
    
    IL int Input(){
        RG int x = 0, z = 1; RG char c = getchar();
        for(; c < '0' || c > '9'; c = getchar()) z = c == '-' ? -1 : 1;
        for(; c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) + (c ^ 48);
        return x * z;
    }
    
    int a[_], n, s[_], rk[_], sa[_], height[_], tmp[_], t[_];
    ll ans1[_], ans2[_];
    int fa[_], id[_], size[_], mx[_], mn[_];
    char ss[_];
    
    IL int Cmp(RG int i, RG int j, RG int k){
    	return tmp[i] == tmp[j] && i + k <= n && j + k <= n && tmp[i + k] == tmp[j + k];
    }
    
    IL int _Cmp(RG int x, RG int y){
    	return height[x] > height[y];
    }
    
    IL void Suffix_Sort(){
    	RG int m = 26;
    	for(RG int i = 1; i <= n; ++i) ++t[rk[i] = s[i]];
    	for(RG int i = 1; i <= m; ++i) t[i] += t[i - 1];
    	for(RG int i = n; i; --i) sa[t[rk[i]]--] = i;
    	for(RG int k = 1; k <= n; k <<= 1){
    		RG int l = 0;
    		for(RG int i = n - k + 1; i <= n; ++i) tmp[++l] = i;
    		for(RG int i = 1; i <= n; ++i) if(sa[i] > k) tmp[++l] = sa[i] - k;
    		for(RG int i = 0; i <= m; ++i) t[i] = 0;
    		for(RG int i = 1; i <= n; ++i) ++t[rk[tmp[i]]];
    		for(RG int i = 1; i <= m; ++i) t[i] += t[i - 1];
    		for(RG int i = n; i; --i) sa[t[rk[tmp[i]]]--] = tmp[i];
    		swap(tmp, rk), rk[sa[1]] = l = 1;
    		for(RG int i = 2; i <= n; ++i) rk[sa[i]] = Cmp(sa[i - 1], sa[i], k) ? l : ++l;
    		if(l >= n) break;
    		m = l;
    	}
    	for(RG int i = 1, h = 0; i <= n; ++i){
    		if(h) --h;
    		while(s[i + h] == s[sa[rk[i] - 1] + h]) ++h;
    		height[rk[i]] = h;
    	}
    }
    
    IL int Find(RG int x){
    	return fa[x] == x ? x : fa[x] = Find(fa[x]);
    }
    
    int main(RG int argc, RG char* argv[]){
    	Fill(ans2, -127), n = Input(), scanf(" %s", ss + 1);
    	for(RG int i = 1; i <= n; ++i) s[i] = ss[i] - 'a' + 1, a[i] = Input();
    	for(RG int i = 1; i <= n; ++i) fa[i] = id[i] = i, size[i] = 1, mx[i] = mn[i] = a[i];
    	Suffix_Sort(), sort(id + 2, id + n + 1, _Cmp);
    	for(RG int i = 2; i <= n; ++i){
    		RG int fx = Find(sa[id[i] - 1]), fy = Find(sa[id[i]]);
    		ans1[height[id[i]]] += 1LL * size[fx] * size[fy];
    		fa[fy] = fx, size[fx] += size[fy];
    		ans2[height[id[i]]] = max(ans2[height[id[i]]], max(1LL * mx[fx] * mx[fy], 1LL * mx[fx] * mn[fy]));
    		ans2[height[id[i]]] = max(ans2[height[id[i]]], max(1LL * mn[fx] * mx[fy], 1LL * mn[fx] * mn[fy]));
    		mx[fx] = max(mx[fx], mx[fy]);
    		mn[fx] = min(mn[fx], mn[fy]);
    	}
    	for(RG int i = n - 1; ~i; --i) ans1[i] += ans1[i + 1], ans2[i] = max(ans2[i], ans2[i + 1]);
    	for(RG int i = 0; i < n; ++i) printf("%lld %lld
    ", ans1[i], ans2[i] == ans2[n] ? 0 : ans2[i]);
        return 0;
    }
    
    
  • 相关阅读:
    WPF之感触
    C# WinForm 给DataTable中指定位置添加列
    MyEclipse 8.6 download 官方下载地址
    将博客搬至CSDN
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
    Building Microservices with Spring Cloud
  • 原文地址:https://www.cnblogs.com/cjoieryl/p/8457716.html
Copyright © 2020-2023  润新知