BZOJ4382: [POI2015]Podział naszyjnika

来源:互联网 发布:ecshop nginx 伪静态 编辑:程序博客网 时间:2024/06/05 04:05

维护最小差的时候没更新….

随便画一个环手玩,发现对于每种颜色,两个分隔点一定是在这种颜色某两个点中间,我们用每种颜色对这些点标号,每个点有k个标号,可以发现如果两个分割点标号相同,他们就能作为一组答案,hash就行了(貌似单hash会被卡

code:

#include<set>#include<map>#include<deque>#include<queue>#include<stack>#include<cmath>#include<ctime>#include<bitset>#include<string>#include<vector>#include<cstdio>#include<cstdlib>#include<cstring>#include<climits>#include<complex>#include<iostream>#include<algorithm>#define ll long longusing namespace std;inline void down(int &x,const int &y){if(x>y)x=y;}const int maxn = 1100000;const ll hash1 = 1e8+7;const ll hash2 = 2333333;int n,m,c[maxn];int col[maxn],cn[maxn];ll pw1[maxn],pw2[maxn];struct node{    ll h1,h2;    int i;}a[maxn];inline bool cmp(const node x,const node y){return x.h1==y.h1?x.h2<y.h2:x.h1<y.h1;}inline bool cmpi(const node x,const node y){return x.i<y.i;}int cal(const int x,const int y){return abs(n-2*(y-x));}ll cals(const ll x){return x*(x-1)/2;}int main(){    scanf("%d%d",&n,&m);    pw1[0]=pw2[0]=n+1;    for(int i=1;i<=n;i++)     {        scanf("%d",&c[i]),cn[c[i]]++;        pw1[i]=pw1[i-1]*pw1[0]%hash1,pw2[i]=pw2[i-1]*pw2[0]%hash2;    }    for(int i=1;i<=n;i++)    {        a[i]=a[i-1]; a[i].i=i;        int now=c[i];        a[i].h1-=pw1[now]*col[now]%hash1;        a[i].h2-=pw2[now]*col[now]%hash2;        col[now]++; if(col[now]==cn[now]) col[now]=0;        (a[i].h1+=pw1[now]*col[now]%hash1)%=hash1; if(a[i].h1<0) a[i].h1+=hash1;        (a[i].h2+=pw2[now]*col[now]%hash2)%=hash2; if(a[i].h2<0) a[i].h2+=hash2;    }sort(a+1,a+n+1,cmp);    ll ans1=0; int ans2=n+1;    for(int i=1;i<=n;i++)    {        int j; for(j=i+1;j<=n&&a[j].h1==a[i].h1&&a[j].h2==a[i].h2;j++);j--;        if(i==j) continue;        ans1+=cals(j-i+1);        sort(a+i,a+j+1,cmpi);        int head=i,las;        for(int l=i+1;l<=j;l++)        {            int temp;            las=cal(a[head].i,a[l].i);            while(head+1<l&&(temp=cal(a[head+1].i,a[l].i))<las) head++,las=temp;            down(ans2,las=cal(a[head].i,a[l].i));        }        i=j;    }    printf("%lld %d\n",ans1,ans2);    return 0;}
原创粉丝点击