bzoj 4199

没有题面差评

先来遍SA求出h,再给h排序,从大到小计算,并查集维护连续的区间(表达能力太弱。。还是看代码好说话)

 1 #include<bits/stdc++.h>
 2 #define inc(i,l,r) for(int i=l;i<=r;i++)
 3 #define dec(i,l,r) for(int i=l;i>=r;i--)
 4 #define link(x) for(edge *j=h[x];j;j=j->next)
 5 #define mem(a) memset(a,0,sizeof(a))
 6 #define inf 1e18
 7 #define ll long long
 8 #define succ(x) (1<<x)
 9 #define NM 300000+5
10 using namespace std;
11 ll read(){
12     ll x=0,f=1;char ch=getchar();
13     while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();}
14     while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar();
15     return x*f;
16 }
17 char st[NM];
18 int n,m,tmp[NM],top[NM],sa[NM],h[NM],rank[NM];
19 ll f[NM],mx[NM],mn[NM],size[NM],ans[NM],_ans[NM];
20 bool cmp(int x,int y){
21     return h[x]>h[y];
22 }
23 void getsa(){
24     int j;m=256;
25     inc(i,0,n)top[rank[i]=(int)st[i]]++;
26     inc(i,1,m)top[i]+=top[i-1];
27     inc(i,0,n)sa[--top[rank[i]]]=i;
28     for(int k=1;k<=n;k<<=1){
29         inc(i,0,n){
30             j=sa[i]-k;
31             if(j<0)j+=n+1;
32             tmp[top[rank[j]]++]=j;
33         }
34 //        inc(i,0,n)printf("%d ",tmp[i]);printf("\n");
35         sa[tmp[top[0]=0]]=j=0;
36         inc(i,1,n){
37             if(rank[tmp[i]]!=rank[tmp[i-1]]||rank[tmp[i]+k]!=rank[tmp[i-1]+k])
38             top[++j]=i;
39             sa[tmp[i]]=j;
40         }
41         memcpy(rank,sa,sizeof(sa));
42         memcpy(sa,tmp,sizeof(tmp));
43     }
44     j=0;
45     inc(i,0,n)if(rank[i]){
46         if(j)j--;
47         while(st[i+j]==st[sa[rank[i]-1]+j])j++;
48         h[rank[i]]=j;
49     }
50 }
51 int find(int x){
52     return f[x]==x?x:f[x]=find(f[x]);
53 }
54 int main(){
55     freopen("data.in","r",stdin);
56     n=read();
57     scanf("%s",st);
58     st[n]=‘$‘;
59     inc(i,0,n-1)mx[i]=mn[i]=read();
60     getsa();
61     inc(i,0,n-1)f[i]=i,tmp[i]=i+1,size[i]=1;
62     sort(tmp+1,tmp+n+1,cmp);
63     inc(i,0,n-1)_ans[i]=-inf;
64 //    inc(i,1,n)printf("%d ",h[tmp[i]]);printf("\n");
65     inc(i,1,n){
66         int x=find(sa[tmp[i]]),y=find(sa[tmp[i]-1]);
67         if(x==y)continue;
68         ans[h[tmp[i]]]+=(ll)size[x]*size[y];
69         _ans[h[tmp[i]]]=max(_ans[h[tmp[i]]],max((ll)mx[x]*mx[y],(ll)mn[x]*mn[y]));
70         f[y]=x;size[x]+=size[y];
71         mx[x]=max(mx[x],mx[y]);
72         mn[x]=min(mn[x],mn[y]);
73     }
74     dec(i,n-2,0)if(ans[i+1])ans[i]+=ans[i+1],_ans[i]=max(_ans[i],_ans[i+1]);
75     inc(i,0,n-1)if(!ans[i])_ans[i]=0;
76     inc(i,0,n-1)printf("%lld %lld\n",ans[i],_ans[i]);
77     return 0;
78 }

时间: 2024-10-03 13:28:03

bzoj 4199的相关文章

bzoj 4199 &amp;&amp; NOI 2015 品酒大会

一年一度的"幻影阁夏日品酒大会"隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发"首席品酒家"和"首席猎手"两个奖项,吸引了众多品酒师参加. 在大会的晚餐上,调酒师 Rainbow 调制了 nn 杯鸡尾酒.这 nn 杯鸡尾酒排成一行,其中第 ii 杯酒 (1≤i≤n1≤i≤n) 被贴上了一个标签 sisi,每个标签都是 2626 个小写英文字母之一.设 Str(l,r)Str(l,r) 表示第 ll 杯酒到第 rr 杯酒的 r?l+1

[BZOJ]4199 品酒大会(Noi2015)

讲道理是后缀数组裸题吧,虽然知道后缀数组的原理但是小C不会写是什么鬼.. 小C趁着做这题的当儿,学习了一下后缀数组. 网络上的后缀数组模板完全看不懂怎么破,全程照着黄学长的代码抄,感觉黄学长写得还是很优雅的. 求LCP的部分已经崩坏了,小C自己脑补的做法是..倍增?? 看到正确的写法之后小C内心是绝望的,大致意思是:在原字符串中,设相邻两个后缀为Sx.Sx+1,那么有height[x+1]>=height[x]-1.(height数组就是小C代码里的tp数组) Description 一年一度的

BZOJ 4199 [Noi2015]品酒大会:后缀数组 + 并查集

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4199 题意: 给你一个长度为n的字符串s,和一个长为n的数组v. 对于每个整数r∈[0,n-1]: (1)问你有多少对后缀(suffix(i), suffix(j)),满足LCP(suffix(i), suffix(j)) >= r (2)输出mul[r] = max(v[i]*v[j]),其中i,j满足(1)的条件 题解: 先考虑第(1)问. 由于LCP只受连续的一段height中最小

BZOJ 4199: [Noi2015]品酒大会( 后缀数组 + 并查集 )

求出后缀数组后, 对height排序, 从大到小来处理(r相似必定是0~r-1相似), 并查集维护. 复杂度O(NlogN + Nalpha(N)) ----------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> using namespace std; ty

BZOJ 4199 品酒大会

以前一直听说什么后缀数组height合并之类的 表示我这种后缀数组都敲不熟的蒟蒻怎么会写 但是做了做觉得还是很简单的嘛 这个题是有两问的,第一问是求LCP>=R的后缀对有多少个 这个就是AHOI2013 差异 稍微变个形啦 直接逆序建后缀自动机,在parent树上做一个很简单的树P就可以了 因为对于现在parent树而言,任意两点的LCP等于两点在树上的LCA的len 到这里,其实我们已经可以拿到70分了 一部分数据暴力,一部分数据LCP<10也可以暴力,还有一部分数据ai相等,等价于只用求第

bzoj 4199: [Noi2015]品酒大会【后缀数组+单调栈+并查集】

用SA求出height数组,然后发现每个height值都有一个贡献区间(因为点对之间要依次取min) 用单调栈处理出区间,第一问就做完了 然后用并查集维护每个点的贡献(?),从大到小枚举height,因为这样区间是不断增大的所以并查集合并即可 #include<iostream> #include<cstdio> #include<vector> #include<algorithm> using namespace std; const int N=300

BZOJ 1013: [JSOI2008]球形空间产生器sphere

二次联通门 : BZOJ 1013: [JSOI2008]球形空间产生器sphere /* BZOJ 1013: [JSOI2008]球形空间产生器sphere 高斯消元 QAQ SB的我也能终于能秒题了啊 设球心的坐标为(x,y,z...) 那么就可以列n+1个方程,化化式子高斯消元即可 */ #include <cstdio> #include <iostream> #include <cstring> #define rg register #define Max

bzoj 3309 DZY Loves Math - 莫比乌斯反演 - 线性筛

对于正整数n,定义f(n)为n所含质因子的最大幂指数.例如f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0. 给定正整数a,b,求sigma(sigma(f(gcd(i,j)))) (i=1..a, j=1..b). Input 第一行一个数T,表示询问数. 接下来T行,每行两个数a,b,表示一个询问. Output 对于每一个询问,输出一行一个非负整数作为回答. Sample Input 4 7558588 9653114 6514903 445

【BZOJ】[HNOI2009]有趣的数列

[算法]Catalan数 [题解] 学了卡特兰数就会啦>_<! 因为奇偶各自递增,所以确定了奇偶各自的数字后排列唯一. 那么就是给2n个数分奇偶了,是不是有点像入栈出栈序呢. 将做偶数标为-1,做奇数标为+1,显然当偶数多于奇数时不合法,因为它压不住后面的奇数. 然后其实这种题目,打表就可知啦--QAQ 然后问题就是求1/(n+1)*C(2n,n)%p了,p不一定是素数. 参考bzoj礼物的解法. 看到网上清一色的素数筛+分解质因数解法,不解了好久,感觉写了假的礼物-- 后来觉得礼物的做法才比