[SDOI2016Round1]解题报告

21 篇文章 0 订阅
11 篇文章 0 订阅

Day1

T1

题意:求 n1i=0m1j=0max((i xor j)k0)
因为是抑或操作,每一位都是独立的,所以可以一位一位的算贡献。
f[i][a][b][c] 表示第i位时,每个数跟 n,m,k 的大小关系,0表示小于,1表示i位之前都相等,2表示大于。转移的时候美剧当前这一位的数是什么,从高位向低位转移就行了。
复杂度是 O(nlogn)
code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long 
const int N=100;
int T,Mod,ni[N],mi[N],ki[N],len;
LL n,m,K,f[N][2][2][3],g[N][2][2][3];
inline void calc(){
    int i,a,b,c,o0,o1,x,y,z,o;
    g[0][1][1][1]=1;
    for(i=0;i<len;++i)
      for(a=0;a<=1;++a)
        for(b=0;b<=1;++b)
          for(c=0;c<=2;++c)
            if(f[i][a][b][c]+g[i][a][b][c])
              for(o0=0;o0<=1;++o0){
                if(a){
                    if(o0>ni[i+1]) continue;
                    if(o0==ni[i+1]) x=1;
                    if(o0<ni[i+1]) x=0;
                }
                else x=0;
                for(o1=0;o1<=1;++o1){
                    if(b){
                        if(o1>mi[i+1]) continue;
                        if(o1==mi[i+1]) y=1;
                        if(o1<mi[i+1]) y=0;
                    }
                    else y=0;
                    o=o0^o1;
                    if(c==0||c==2) z=c;
                    if(c==1){
                        if(o>ki[i+1]) z=2;
                        if(o==ki[i+1]) z=1;
                        if(o<ki[i+1]) z=0;
                    }
                    g[i+1][x][y][z]=(g[i+1][x][y][z]+g[i][a][b][c])%Mod;
                    f[i+1][x][y][z]=(f[i+1][x][y][z]+f[i][a][b][c]*2LL+g[i][a][b][c]*(LL)o)%Mod;
                }
              }
}
int main(){
    scanf("%d",&T);
    while(T--){
        LL x;
        int i;
        memset(f,0,sizeof(f));
        memset(g,0,sizeof(g));
        memset(ni,0,sizeof(ni));
        memset(mi,0,sizeof(mi));
        memset(ki,0,sizeof(ki));
        scanf("%lld%lld%lld%d",&n,&m,&K,&Mod);
        for(x=n;x;x>>=1) ni[++ni[0]]=x&1LL;
        for(x=m;x;x>>=1) mi[++mi[0]]=x&1LL;
        for(x=K;x;x>>=1) ki[++ki[0]]=x&1LL; 
        len=max(ni[0],max(mi[0],ki[0]));
        for(i=1;i<=(len>>1);++i){
            swap(ni[i],ni[len-i+1]);
            swap(mi[i],mi[len-i+1]);
            swap(ki[i],ki[len-i+1]);
        }
        calc();
        printf("%lld\n",(f[len][0][0][2]-(K%Mod*g[len][0][0][2])%Mod+Mod)%Mod);
    }
}

T2

题意:给出n种数字,第i个是ai,个数是bi,权值是ci。如果 ai|aj 而且 aiaj 是一个质数,那么这两个数字就能获得 cicj 的价值,要求总价值不小于0的情况下求最多的配对数。
配对关系是一个二分图,所以建出费用流的图来,当跑到费用小于0的时候,处理一下当前的流量,退出就行了。
code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define T n+2
#define D 795
#define LL long long 
#define inf 1000000000
#define INF 10000000000000LL
const int N=800;
const int M=100000;
const int O=2000000;
bool flag[M+10],use[N],f[N];
struct S{int st,en,va;LL co;}aa[O];
int n,a[N],b[N],c[N],prime[M+10],d[N],va,point[N],pre[N],next[O],map[N][N],tot=1,co[N];
int l[N],to[N];
LL dis[N];
inline void prepare(){
    int i,j;
    for(i=2;i<=M;++i){
        if(!flag[i]) prime[++prime[0]]=i;
        for(j=1;j<=prime[0]&&i*prime[j]<=M;++j){
            flag[i*prime[j]]=true;
            if(i%prime[j]==0) break;
        }
    }
}
inline void add(int x,int y,int z,LL co){
    next[++tot]=point[x];point[x]=tot;
    aa[tot].st=x;aa[tot].en=y;aa[tot].va=z;aa[tot].co=co;
    next[++tot]=point[y];point[y]=tot;
    aa[tot].st=y;aa[tot].en=x;aa[tot].va=0;aa[tot].co=-co;
}
inline bool check(int x,int y){
    int i,j,now,num=0;
    if((a[x]%a[y])||(a[x]==a[y])) return false;
    now=a[x]/a[y];
    for(i=1;i<=prime[0];++i){
        while(now%prime[i]==0) ++num,now/=prime[i];
        if(num>1) return false;
        if(now==1) return true;
    }
    if(now!=1) ++num;
    return num==1;
}
inline void paint(int x,int kind){
    int i;
    co[x]=kind;
    for(i=1;i<=n;++i)
      if(map[x][i]&&!co[i])
        paint(i,kind==1?2:1);
}
inline LL SPFA(int x,int y){
    int h=0,t=1,i,u;
    l[t]=x;
    for(i=1;i<=T;++i) dis[i]=-INF;
    dis[x]=0;
    while(h!=t){
        h=h%D+1;u=l[h];f[u]=true;
        for(i=point[u];i;i=next[i])
          if(aa[i].va>0&&dis[aa[i].en]<dis[u]+aa[i].co){
            dis[aa[i].en]=dis[u]+aa[i].co;
            pre[aa[i].en]=i;
            if(f[aa[i].en]){
                f[aa[i].en]=false;
                t=t%D+1;
                l[t]=aa[i].en;
            }
          }
    }
    return dis[y];
}
inline int ISAP(int x,int y){
    int minn=inf,i;
    for(i=y;i!=x;i=aa[pre[i]].st)
      minn=min(minn,aa[pre[i]].va);
    for(i=y;i!=x;i=aa[pre[i]].st){
        aa[pre[i]].va-=minn;
        aa[pre[i]^1].va+=minn;
    }
    return minn;
}
int main(){
    int i,j,o=0,num=0,maxn=0;
    prepare();
    scanf("%d",&n);
    for(i=1;i<=n;++i) scanf("%d",&a[i]);
    for(i=1;i<=n;++i) scanf("%d",&b[i]);
    for(i=1;i<=n;++i) scanf("%d",&c[i]),o+=(c[i]==0);
    for(i=1;i<=n;++i)
      for(j=1;j<=n;++j)
        if(check(i,j)) map[i][j]=map[j][i]=1;
    for(i=1;i<=n;++i)
      if(!co[i]) paint(i,1);
    for(i=1;i<=n;++i)
      if(co[i]==1) add(1,i+1,b[i],0);
      else add(i+1,T,b[i],0);
    for(i=1;i<=n;++i)
      for(j=i+1;j<=n;++j)
        if(map[i][j]||map[j][i]){
            int x=i,y=j;
            if(co[x]==2) swap(x,y);
            add(x+1,y+1,inf,(LL)c[x]*c[y]);
        }
    memset(f,1,sizeof(f));
    LL minn,ans=0;
    while(minn!=-INF){
        minn=SPFA(1,T);
        if(minn!=-INF){
            int now=ISAP(1,T);
            ans=ans+minn*(LL)now;
            if(ans<0LL){
                ans-=minn*(LL)now;
                printf("%d\n",num+min(now,(int)(-ans/minn)));
                return 0;
            }
            num+=now;
        }
    }
    printf("%d\n",num);
}

T3

题意:给出一棵树,有点权和边权,有两种操作,一种是将一条路径上的点权修改成 min(v[x],adis[x]+b) dis[x] 表示x到起点的距离(只算边权)。另一种是询问a到b路径中最小的点权。
第一种修改可以看成是往树上的一段区间中加入一个线段。这个东西可以用线段树维护。用线段树维护这个区间的线段的斜率和截距。每次向这个区间中加入一条新的线段的时候,看一下这段区间中原来的线段和新加入的线段哪一个对这段区间的影响更大,将影响小的线段下放到它有影响的子树,每次一直这样下放到叶子节点。这样每次插入的复杂度是 O(log2n)
每次查询的时候只需要看一下这段区间中的最小值和这段区间中所保存的线段的两个端点的情况就行了,复杂度是 O(logn)
这道题每次的dis数组还是不知道的,可以在加入线段的时候顺便将lca传进去(常数大了好多。。。)
再加上链剖,总的复杂度就是 O(nlog3n)
code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mid (l+r)/2
#define L k<<1,l,mid
#define R k<<1|1,mid+1,r
#define LL long long
#define D 123456789123456789LL
const int N=100010;
LL dis[N],a,b;
struct S{int st,en,va;}aa[N<<1];
struct T{int lca,st,kind;LL k,b,minn;}tr[N<<2];
int n,m,point[N],next[N<<1],tot,deep[N],siz[N],son[N],belong[N],fa[N][21],q[N],pos[N],dfsn,cur[N],lca,to[N],flag[N<<2];
inline int in(){
    int f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline int IN(){
    LL f=1,x=0;char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-') f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
inline void add(int x,int y,int z){
    next[++tot]=point[x];point[x]=tot;
    aa[tot].st=x;aa[tot].en=y;aa[tot].va=z;
    next[++tot]=point[y];point[y]=tot;
    aa[tot].st=y;aa[tot].en=x;aa[tot].va=z;
}
inline void prepare(){
    int h=1,t=1,u,i,j;
    q[h]=1;
    while(h<=t){
        u=q[h];
        for(i=point[u];i;i=next[i])
          if(aa[i].en!=fa[u][0]){
            q[++t]=aa[i].en;
            deep[aa[i].en]=deep[u]+1;
            fa[aa[i].en][0]=u;
            dis[aa[i].en]=dis[u]+(LL)aa[i].va;
            for(j=1;j<=20;++j)
              fa[aa[i].en][j]=fa[fa[aa[i].en][j-1]][j-1];
          }
        h+=1;
    }
    for(i=t;i;--i){
        u=q[i];siz[u]=1;
        for(j=point[u];j;j=next[j])
          if(aa[j].en!=fa[u][0]){
            siz[u]+=siz[aa[j].en];
            if(siz[aa[j].en]>siz[son[u]]) son[u]=aa[j].en;
          }
    }
    int now=1;
    for(i=1;i<=n;++i) cur[i]=point[i];
    while(now){
        if(!pos[now]){
            pos[now]=++dfsn;
            to[dfsn]=now;
            belong[now]=(now==son[fa[now][0]] ? belong[fa[now][0]] : now);
            now=(son[now] ? son[now] : fa[now][0]);
        }
        else{
            for(i=cur[now];i&&(aa[i].en==fa[now][0]||aa[i].en==son[now]);i=next[i]);
            cur[now]=next[i];
            belong[aa[i].en]=aa[i].en;
            now=(i ? aa[i].en : fa[now][0]);
        }
    }
}
inline int LCA(int x,int y){
    if(deep[x]<deep[y]) swap(x,y);
    int t=deep[x]-deep[y],i;
    for(i=0;i<=20;++i)
      if(t&(1<<i)) x=fa[x][i];
    for(i=20;~i;--i)
      if(fa[x][i]!=fa[y][i])
        x=fa[x][i],y=fa[y][i];
    return x==y?x:fa[x][0];
}
inline void build(int k,int l,int r){
    if(l==r){
        tr[k].k=0;
        tr[k].kind=-1;
        tr[k].lca=to[l];
        tr[k].b=tr[k].minn=D;
        return ;
    }
    build(L);build(R);
    tr[k]=tr[k<<1];
}
inline int LL calc(int x,int y,int z,int kind){
    x=to[x];
    if(kind==0) return dis[z]-dis[x];
    if(kind==1) return dis[z]-dis[y]+dis[x]-dis[y];
}
inline void insert(int k,int l,int r,int x,int y,T now){
    if(x<=l&&y>=r){
        LL minn=D;
        minn=min(minn,calc(l,now.lca,now.st,now.kind)*now.k+now.b);
        minn=min(minn,calc(r,now.lca,now.st,now.kind)*now.k+now.b);
        now.minn=tr[k].minn=min(tr[k].minn,minn);
        if(!flag[k]){
            flag[k]=1;
            tr[k]=now;
            return ;
        }
        int o1=calc(l,now.lca,now.st,now.kind)*now.k+now.b<calc(l,tr[k].lca,tr[k].st,tr[k].kind)*tr[k].k+tr[k].b;
        if(l==r){
            if(o1) tr[k]=now;
            return ;
        }
        int o2=calc(mid,now.lca,now.st,now.kind)*now.k+now.b<calc(mid,tr[k].lca,tr[k].st,tr[k].kind)*tr[k].k+tr[k].b;
        int o3=calc(r,now.lca,now.st,now.kind)*now.k+now.b<calc(r,tr[k].lca,tr[k].st,tr[k].kind)*tr[k].k+tr[k].b;
        if(o1&&o3){
            tr[k]=now;
            return ;
        }
        if(!o1&&!o3) return;
        if(o2){
            swap(tr[k],now);
            o1^=1;o3^=1;
        }
        if(o1) insert(L,x,y,now);
        if(o3) insert(R,x,y,now);
        return ;
    }
    if(x<=mid) insert(L,x,y,now);
    if(y>mid) insert(R,x,y,now);
    tr[k].minn=min(tr[k].minn,min(tr[k<<1].minn,tr[k<<1|1].minn));
}
inline LL query(int k,int l,int r,int x,int y){
    LL minn=D;
    if(x<=l&y>=r){
        LL o_l=calc(l,tr[k].lca,tr[k].st,tr[k].kind);
        LL o_r=calc(r,tr[k].lca,tr[k].st,tr[k].kind);
        return min(tr[k].minn,min(o_l*tr[k].k+tr[k].b,o_r*tr[k].k+tr[k].b));
    }
    minn=min(minn,calc(max(x,l),tr[k].lca,tr[k].st,tr[k].kind)*tr[k].k+tr[k].b);
    minn=min(minn,calc(min(y,r),tr[k].lca,tr[k].st,tr[k].kind)*tr[k].k+tr[k].b);
    if(x<=mid) minn=min(minn,query(L,x,y));
    if(y>mid) minn=min(minn,query(R,x,y));
    return minn;
}
inline void change(int x,int y,int st,int kind){
    int i,j;
    T now=(T){lca,st,kind,a,b,D};
    while(belong[x]!=belong[y]){
        insert(1,1,n,pos[belong[x]],pos[x],now);
        x=fa[belong[x]][0];
    }
    insert(1,1,n,pos[y],pos[x],now);
}
inline LL ask(int x,int y){
    LL minn=D;
    while(belong[x]!=belong[y]){
        minn=min(minn,query(1,1,n,pos[belong[x]],pos[x]));
        x=fa[belong[x]][0];
    }
    minn=min(minn,query(1,1,n,pos[y],pos[x]));
    return minn;
}
int main(){
    int i,j,x,y,t,z;
    n=in();m=in();
    for(i=1;i<n;++i){
        x=in();y=in();z=in();
        add(x,y,z);
    }
    prepare();
    build(1,1,n);
    while(m--){
        t=in();x=in();y=in();
        lca=LCA(x,y);
        if(t==1){
            a=IN();b=IN();
            change(x,lca,x,0);
            change(y,lca,x,1);
        }
        if(t==2) printf("%lld\n",min(ask(x,lca),ask(y,lca)));
    }
}

Day2

T1

题意:每次向一个字符串的结尾加一个字符,输出当前有多少种不同的非空子串。
先将这个字符串全读进来,然后把字符串反过来建后缀数组。总的答案就是 n(n+1)2n1i=1height[i]
因为要动态的查询,所以维护一个rank的权值线段树,每次加入一个之后查询一下前驱和后继,每次更新的答案就是: nilcp(now,pre)lcp(now,sub)+lcp(pre,sub)
code:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define inf 0x7fffffff
const int N=100010;
struct S{int minn,maxn;}tr[N<<2];
int n,a[N],b[N],m,t1[N],t2[N],sa[N],rank[N],c[N],height[N],st[N][21],Log[N];
inline int in(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x;
}
inline bool cmp(int *y,int p,int q,int k){
    int o0,o1;
    o0=(p+k>=n)?-1:y[p+k];
    o1=(q+k>=n)?-1:y[q+k];
    return o0==o1&&y[p]==y[q];
}
inline void build_sa(){
    int i,k,p,*x=t1,*y=t2;
    for(i=0;i<m;++i) c[i]=0;
    for(i=0;i<n;++i) ++c[x[i]=a[i]];
    for(i=1;i<m;++i) c[i]+=c[i-1];
    for(i=n-1;~i;--i) sa[--c[x[i]]]=i;
    for(k=1;k<=n;k<<=1){
        for(p=0,i=n-k;i<n;++i) y[p++]=i;
        for(i=0;i<n;++i) if(sa[i]>=k) y[p++]=sa[i]-k;
        for(i=0;i<m;++i) c[i]=0;
        for(i=0;i<n;++i) ++c[x[y[i]]];
        for(i=1;i<m;++i) c[i]+=c[i-1];
        for(i=n-1;~i;--i) sa[--c[x[y[i]]]]=y[i];
        swap(x,y);
        x[sa[0]]=0;m=1;
        for(i=1;i<n;++i) x[sa[i]]=(cmp(y,sa[i],sa[i-1],k)?m-1:m++);
        if(m>=n) break;
    }
}
inline void build_height(){
    int i,j,k=0;
    for(i=0;i<n;++i) rank[sa[i]]=i;
    for(i=0;i<n;++i){
        k=k?--k:k;
        j=sa[rank[i]-1];
        while(a[i+k]==a[j+k]) ++k;
        height[rank[i]]=k;
    }
    /*------------st------------*/
    memset(st,127/3,sizeof(st));    
    for(i=0;i<n;++i) st[i][0]=height[i];
    for(j=1;j<=20;++j)
      for(i=0;i+(1<<(j-1))<n;++i)
        st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
    for(j=0,i=1;i<=n;++i){
        if((1<<(j+1))<=i) ++j;
        Log[i]=j;
    }
}
inline int LCP(int x,int y){
    int k=Log[y-x];++x;
    return min(st[x][k],st[y-(1<<k)+1][k]);   
}
#define mid (l+r)/2
#define L k<<1,l,mid
#define R k<<1|1,mid+1,r
inline S update(S x,S y){
    S ans;
    ans.maxn=max(x.maxn,y.maxn);
    ans.minn=min(x.minn,y.minn);
    return ans;
}
inline void build_tree(int k,int l,int r){
    if(l==r){
        tr[k].minn=inf;
        tr[k].maxn=-inf;
        return ;
    }
    build_tree(L);build_tree(R);
    tr[k]=update(tr[k<<1],tr[k<<1|1]);
}
inline void insert(int k,int l,int r,int x){
    if(l==r){
        tr[k].maxn=tr[k].minn=l;
        return ;
    }
    if(x<=mid) insert(L,x);
    else insert(R,x);
    tr[k]=update(tr[k<<1],tr[k<<1|1]);
}
inline S query(int k,int l,int r,int x,int y){
    S ans1,ans2;
    bool f1=false,f2=false;
    if(x<=l&&y>=r) return tr[k];
    if(x<=mid) ans1=query(L,x,y),f1=true;
    if(y>mid) ans2=query(R,x,y),f2=true;
    if(f1&&f2) return update(ans1,ans2);
    else return f1?ans1:ans2;
}
int main(){
    int i;
    n=in();
    for(i=n-1;~i;--i) a[i]=b[i]=in();
    sort(b+1,b+n+1);
    m=unique(b+1,b+n+1)-b-1;
    for(i=0;i<n;++i) a[i]=lower_bound(b+1,b+m+1,a[i])-b-1;
    build_sa();
    build_height();
    build_tree(1,0,n-1);
    for(LL ans=0,i=n-1;~i;--i){
        ans+=(LL)(n-i);
        int now=rank[i];
        int pre=now?query(1,0,n-1,0,now-1).maxn:-inf;
        int sub=(now==n-1)?inf:query(1,0,n-1,now+1,n-1).minn;
        if(pre!=-inf) ans-=(LL)LCP(pre,now);
        if(sub!=inf) ans-=(LL)LCP(now,sub);
        if(pre!=-inf&&sub!=inf) ans+=(LL)LCP(pre,sub);
        insert(1,0,n-1,now);
        printf("%lld\n",ans);
    }
}

T2

题意:求有多少长度为n的序列,满足1~n只出现过一次,而且恰好有m个数满足 a[i]=i
答案就是 C(n,m)f[nm]
C(n,m) 表示m个满足条件的数怎样选的方案数,再乘上剩下的所有 nm 个数都不在多对应的位置上的方案数,也就是错排。
错拍的公式就是: f[i]=(i1)(f[i1]+f[i2])
求c的时候预处理一下阶乘。
code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
#define Mod 1000000007LL
const int M=1000000;
LL f[M+10],g[M+10];
int T,n,m;
inline int in(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x;
}
inline LL quickpow(LL x,LL y){
    LL ans=1;
    while(y){
        if(y&1LL) ans=(ans*x)%Mod;
        y>>=1LL; x=(x*x)%Mod;
    }
    return ans;
}
int main(){
    int i;  
    T=in();
    for(f[1]=0LL,f[2]=1LL,f[0]=1LL,i=3;i<=M;++i) f[i]=(LL)(i-1)*((f[i-1]+f[i-2])%Mod)%Mod;
    for(g[1]=g[0]=1LL,i=2;i<=M;++i) g[i]=(g[i-1]*(LL)i)%Mod;
    while(T--){
        n=in();m=in();
        if(m>n){
            printf("0\n");
            continue;
        }
        LL ans=f[n-m]*((g[n]*quickpow(g[m],Mod-2)%Mod)*quickpow(g[n-m],Mod-2)%Mod)%Mod;
        printf("%lld\n",ans);
    }
}

T3

题意:有一个长度为n的序列,每个节点都有一个权值,分成m份,求m份的最小的方差是多少。答案要求 m2
ans=mmi=1(xix¯)2
      =mmi1(xi2+x¯22xix¯)
拆开之后,后面两项都是常数,就相当于求每段的平方和的最大。这个东西可以斜率优化。
code:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define LL long long
const int N=3010;
LL f[N][N],a[N];
int n,m,h[N],t[N],q[N][N];
inline LL pow(LL x){return x*x;}
inline LL get_son(int x,int y,int z){
    return f[z][x]+pow(a[x])-f[z][y]-pow(a[y]);
}
inline LL get_fa(int x,int y){
    return a[x]-a[y];
}
inline LL calc(int x,int y,int z){
    return f[z][x]+pow(a[y]-a[x]);
}
int main(){
    int i,j;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;++i) 
      scanf("%lld",&a[i]),a[i]+=a[i-1];
    memset(f,127/3,sizeof(f));
    for(j=0;j<=m;++j) f[j][0]=0,q[j][h[j]=t[j]=1]=0;
    for(j=1;j<=m;++j)
      for(i=1;i<=n;++i){
        while(h[j-1]<t[j-1]&&get_son(q[j-1][h[j-1]+1],q[j-1][h[j-1]],j-1)<get_fa(q[j-1][h[j-1]+1],q[j-1][h[j-1]])*(LL)a[i]*2LL) ++h[j-1];
        f[j][i]=calc(q[j-1][h[j-1]],i,j-1);
        while(h[j]<t[j]&&get_son(i,q[j][t[j]],j)*get_fa(q[j][t[j]],q[j][t[j]-1])<get_son(q[j][t[j]],q[j][t[j]-1],j)*get_fa(i,q[j][t[j]])) --t[j];
        q[j][++t[j]]=i;
      }
    printf("%lld\n",f[m][n]*(LL)m-pow(a[n]));
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值