D1T1

并查集。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=;
const int maxcnt=*maxN; int N;
struct Ta{int e,x,y;}a[maxN+];
int cnt,bak[maxcnt+]; int pa[maxcnt+];
inline int findroot(int a){return pa[a]<?a:pa[a]=findroot(pa[a]);}
inline void BCJ_Union(int a,int b)
{
int f1=findroot(a),f2=findroot(b);
if(f1==f2)return;
if(pa[f1]>pa[f2])swap(f1,f2);
pa[f1]=pa[f1]+pa[f2];
pa[f2]=f1;
} int main()
{
freopen("prog.in","r",stdin);
freopen("prog.out","w",stdout);
int i;
for(int Case=gint();Case;Case--)
{
N=gint();
re(i,,N){a[i].x=gint();a[i].y=gint();a[i].e=gint();}
cnt=;
re(i,,N){bak[++cnt]=a[i].x;bak[++cnt]=a[i].y;}
sort(bak+,bak+cnt+);
cnt=unique(bak+,bak+cnt+)-bak-;
re(i,,N){a[i].x=lower_bound(bak+,bak+cnt+,a[i].x)-bak;a[i].y=lower_bound(bak+,bak+cnt+,a[i].y)-bak;}
re(i,,cnt)pa[i]=-;
re(i,,N)if(a[i].e==)BCJ_Union(a[i].x,a[i].y);
int flag=;
re(i,,N)if(a[i].e== && findroot(a[i].x)==findroot(a[i].y)){flag=;break;}
if(flag)PF("YES\n");else PF("NO\n");
}
return ;
}

D1T2

树链剖分+线段树。

树链剖分中,我们在求边的编号的时候,我们可以用DFS,虽然这样麻烦一点,但是可以保证同一棵子树的编号在线段树中是连续的。

但考试的时候并没有想到这一点。

然后用了LCT,打了8KB,我都不想说话了。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=;
const int maxQ=; struct Tnode
{
Tnode *fa,*son[],*path_parent;
int R,L,val,add;
inline Tnode(){fa=son[]=son[]=path_parent=;R=L=val=add=;}
inline void down()
{
if(add!=)
{
if(son[]){son[]->val+=add;son[]->add+=add;}
if(son[]){son[]->val+=add;son[]->add+=add;}
add=;
}
}
}; int N,Q;
int fa[maxN+];
int now,first[maxN+];
struct Tedge{int v,next;}edge[maxN+];
int dep[maxN+];
int jump[maxN+][];
Tnode *pos[maxN+]; inline void addedge(int u,int v)
{
now++;
edge[now].v=v;
edge[now].next=first[u];
first[u]=now;
} int head,tail,que[maxN+];
int size[maxN+],heavy[maxN+],top[maxN+],w[maxN+],cnt;
inline void BFS()
{
int i,j,u,v;
dep[que[head=tail=]=]=;
while(head<=tail)
{
u=que[head++];
for(i=first[u],v=edge[i].v;i!=-;i=edge[i].next,v=edge[i].v)dep[que[++tail]=v]=dep[u]+;
}
re(i,,tail)
{
u=que[i];
jump[u][]=fa[u];
re(j,,)jump[u][j]=jump[jump[u][j-]][j-];
}
red(j,tail,)
{
u=que[j];
size[u]=;
heavy[u]=-;
for(i=first[u],v=edge[i].v;i!=-;i=edge[i].next,v=edge[i].v)
{
size[u]+=size[v];
if(heavy[u]==- || size[v]>size[heavy[u]])heavy[u]=v;
}
}
top[]=;
re(i,,tail)
{
u=que[i];
if(heavy[fa[u]]==u) top[u]=top[fa[u]]; else top[u]=u;
}
mmst(w,-);
cnt=;
re(i,,tail)
{
u=que[i];
if(w[u]!=-)continue;
int r=u;
while(r!=-){w[r]=++cnt;r=heavy[r];}
}
}; int tree[*maxN+];
inline void down(int root)
{
if(tree[root]!=)
{
tree[root*]=tree[root*+]=tree[root];
tree[root]=;
}
}
inline void update(int root,int l,int r,int x,int y,int val)
{
if(l>r || x>y || r<x || y<l) return;
if(x<=l && r<=y){tree[root]=val;return;}
down(root);
int mid=(l+r)/;
update(root*,l,mid,x,y,val);
update(root*+,mid+,r,x,y,val);
}
inline int ask(int root,int l,int r,int x)
{
if(l<=x && x<=r && tree[root]!=) return tree[root];
if(x<=l && r<=x) return tree[root];
down(root);
int mid=(l+r)/;
if(x<=mid) return ask(root*,l,mid,x); else return ask(root*+,mid+,r,x);
}
inline void Cover(int a,int b,int val)
{
int f1=top[a],f2=top[b];
while(f1!=f2)
{
if(dep[f1]<dep[f2]){swap(f1,f2);swap(a,b);}
update(,,cnt,w[f1],w[a],val);
a=fa[f1];
f1=top[a];
}
if(dep[a]>dep[b])swap(a,b);
update(,,cnt,w[a],w[b],val);
}
inline Tnode *findp(int x)
{
if(x==) return pos[];
x=ask(,,cnt,w[x]);
return (x==)?:pos[x];
} inline void Splay_Rotate(Tnode *x,int flag)
{
Tnode *y=x->fa,*z=y->fa;
y->son[flag^]=x->son[flag];if(x->son[flag])x->son[flag]->fa=y;
x->son[flag]=y;y->fa=x;
x->path_parent=y->path_parent;y->path_parent=;
x->fa=z;if(z)z->son[(y==z->son[])]=x;
}
inline void Splay(Tnode *x)
{
Tnode *y,*z;
while(x->fa)
{
y=x->fa;z=y->fa;
if(z)z->down();y->down();x->down();
if(!z){Splay_Rotate(x,x==y->son[]);return;}
int L=(x==y->son[]),R=(y==z->son[]);
if(L==R){Splay_Rotate(y,L);Splay_Rotate(x,R);continue;}
if(L!=R){Splay_Rotate(x,L);Splay_Rotate(x,R);continue;}
}
x->down();
}
inline void LCT_Access(Tnode *x)
{
Tnode *y;
for(y=;x;y=x,x=x->path_parent)
{
Splay(x);
if(x->son[]){x->son[]->fa=;x->son[]->path_parent=x;}
x->son[]=y;
if(y){y->fa=x;y->path_parent=;}
}
}
inline void LCT_update(Tnode *x,int v)
{
LCT_Access(x);
Splay(x);
x->val+=v;
x->add+=v;
x->down();
}
inline void LCT_Delete(Tnode *u,Tnode *v)
{
LCT_Access(u);
LCT_Access(v);
u->path_parent=;
}
inline int swim(int x,int H)
{
int res=x;
for(int i=;H!=;H/=,i++)if(H&)res=jump[res][i];
return res;
}
inline void LCT_Fen(Tnode *x,int ca)
{
int R,L,G;
Tnode *p;
if(ca==x->R)return;
R=x->R;
L=x->L;
G=swim(R,dep[R]-dep[ca]-);
p=findp(fa[L]);
LCT_Delete(x,p);
pos[ca]=new Tnode;
pos[ca]->path_parent=p;
pos[ca]->R=ca;
pos[ca]->L=L;
pos[ca]->val=x->val;
Cover(ca,L,ca);
x->path_parent=pos[ca];
x->L=G;
x->val-=dep[ca]-dep[L]+;
} inline int isblack(int x)
{
Tnode *p=findp(x);
if(!p)return ;
LCT_Access(p);
Splay(p);
Tnode *t=p;t->down();
while(t->son[]){t=t->son[];t->down();}
return t==pos[];
} inline int findL(int x)
{
int i;
red(i,,)if(jump[x][i]!= && !isblack(jump[x][i])) x=jump[x][i];
return x;
} int main()
{
freopen("manager.in","r",stdin);
freopen("manager.out","w",stdout);
int i;
N=gint();
now=-;mmst(first,-);
re(i,,N)
{
fa[i]=gint()+;
addedge(fa[i],i);
}
BFS();
pos[]=new Tnode;
Q=gint();
while(Q--)
{
char s[];int x,ca,R,L;
Tnode *p;
SF("%s%d\n",s,&x);x++;
switch(s[])
{
case 'i':
if(isblack(x)){PF("0\n");continue;}
L=findL(x);
ca=fa[L];
p=findp(ca);
LCT_Fen(p,ca);
pos[x]=new Tnode;
pos[x]->R=x;pos[x]->L=L;
Cover(x,L,x);
pos[x]->path_parent=findp(ca);
LCT_update(pos[x],dep[x]-dep[ca]);
PF("%d\n",dep[x]-dep[ca]);
break;
case 'u':
if(!isblack(x)){PF("0\n");continue;}
p=findp(x);
R=p->R;
L=p->L;
ca=fa[L];
PF("%d\n",p->val-(dep[x]-dep[L]));
LCT_update(p,-p->val);
LCT_Delete(p,findp(ca));
//////////
if(x==L)continue;
x=fa[x];
pos[x]=new Tnode;
pos[x]->R=x;pos[x]->L=L;
Cover(x,L,x);
pos[x]->path_parent=findp(ca);
LCT_update(pos[x],dep[x]-dep[ca]);
break;
}
}
return ;
}

D1T3

背包+状压DP。

神题。。。。。。

ppt讲得比较清晰了。

30%的做法:

集合A和集合B互质就是没有包含相同的质因数,我们将每个数分解质因数。

分解质因数求出每个数包含哪些质因子,使用二进制状态压缩,存在s[i]里,每个数看作一个物品,做一次二进制状态的背包DP。

容易得到g[j|s[i]]=(g[j|s[i]]+g[j])%Mod

这是一个背包,所以j倒序循环。

100%的做法:

注意到小于等于sqrt(N)的质因数最多只有9个,每一个数最多包含一个大于sqrt(N)的质因数。

s[i]就表示i在2...sqrt(N)中包含哪些质因子,使用二进制状态压缩。

f(i)[x][y]表示可以使用前i个大质数和全部小质数,A集合包含的小质数的状态为x(二进制),B集合包含的小质数的状态为y(二进制)时的方案数。

容易得到初值f(0)[x][y]=g[x]*g[y]%Mod,其中x&y==0。

其中i这一维可以在背包中忽略。

转移时,枚举包含第i个大质数的所有整数z,他们可以某些且至少一个分配在A集合,可以某些且至少一个分配在B集合,也可以全部丢弃不用。单是绝对不可以某些分配在A集合,某些分配在B集合。

我们在做第i个大质数的时候,记d[x][y][0]表示A集合包含的小质数的状态为x(二进制),B集合包含的小质数的状态为y(二进制),包含第i个大质数的所有至少一个整数z都分配在A集合中的方案数。

同理,d[x][y][0]表示A集合包含的小质数的状态为x(二进制),B集合包含的小质数的状态为y(二进制),包含第i个大质数的某些且至少一个整数z都分配在B集合中的方案数。

分给A:d[x|s[z]][y][0]=(d[x|s[z]][y][0]+d[x][y][0]+f[x][y])%Mod

分给B:d[x][y|s[z]][1]=(d[x][y|s[z]][1]+d[x][y][0]+f[x][y])%Mod

这是一个背包,所以x和y倒序循环。

至于为什么还要加上一个f[x][y],因为d[x][y][0]是前面用了至少一个整数z,但是有可能前面没有用整数z,用了当前的整数z,所以要加f[x][y]。

累加:f[x][y]=(f[x][y]+d[x][y][0]+d[x][y][1])%Mod

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=; int N;
LL Mod;
int flag[maxN+];
int cnt,ge,prime[maxN+];
int s[maxN+];
LL g[(<<)+];
LL f[(<<)+][(<<)+],d[(<<)+][(<<)+][];
LL ans; #define wei(v,k) (((v)>>((k)-1))&1)
#define two(k) (1<<(k-1)) int main()
{
freopen("dinner.in","r",stdin);
freopen("dinner.out","w",stdout);
int i,j,k;
N=gint();Mod=gll();
re(i,,N)
{
if(!flag[i])prime[++cnt]=i;
for(j=;j<=cnt && prime[j]*i<=N;j++)
{
flag[i*prime[j]]=;
if(i%prime[j]==)break;
}
}
if(cnt<=)
{
re(i,,N)re(j,,cnt)if(i%prime[j]==)s[i]|=two(j);
g[]=;
re(i,,N)red(j,(<<cnt)-,)g[j|s[i]]=(g[j|s[i]]+g[j])%Mod;
ans=;
re(i,,(<<cnt)-)re(j,,(<<cnt)-)if((i&j)==)ans=(ans+g[i]*g[j])%Mod;
cout<<ans<<endl;
}
else
{
ge=;
re(i,,N)re(j,,ge)if(i%prime[j]==)s[i]|=two(j);
g[]=;
re(i,,N)
{
int t=i;
re(j,,ge)while(t%prime[j]==)t/=prime[j];
if(t!=)continue;
red(j,(<<ge)-,)g[j|s[i]]=(g[j|s[i]]+g[j])%Mod;
}
re(i,,(<<ge)-)re(j,,(<<ge)-)if((i&j)==)f[i][j]=g[i]*g[j]%Mod;
re(k,ge+,cnt)
{
mmst(d,);
for(int v=prime[k];v<=N;v+=prime[k])
red(i,(<<ge)-,)red(j,(<<ge)-,)if((i&j)==)
{
if(((i|s[v])&j)==)d[i|s[v]][j][]=(d[i|s[v]][j][]+d[i][j][]+f[i][j])%Mod;
if((i&(j|s[v]))==)d[i][j|s[v]][]=(d[i][j|s[v]][]+d[i][j][]+f[i][j])%Mod;
}
re(i,,(<<ge)-)re(j,,(<<ge)-)if((i&j)==)f[i][j]=(f[i][j]+d[i][j][]+d[i][j][])%Mod;
}
ans=;
re(i,,(<<ge)-)re(j,,(<<ge)-)if((i&j)==)ans=(ans+f[i][j])%Mod;
cout<<ans<<endl;
}
return ;
}

D2T1

多叉哈夫曼树。

如果K=2,那就是裸的哈夫曼树。现在K不是2,就是多叉哈夫曼树。

根据二叉哈夫曼树的类比,我们可以得到多叉哈夫曼树的做法:将前K小的点拿出来,然后删去,再加入一个权值等于和的点。

但是有几点地方要注意,有可能最后会剩下小于K个,这样无法取,我们在一开始的时候就补若干个0,使得个数为(K-1)的倍数+1

对于第二问,我们可以可以再排序的时候设置第二关键字,先取深度小的。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<LL,LL> PLL;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} int N,K; struct cmp{inline bool operator ()(PLL x,PLL y){return (x.fi==y.fi)?x.se>y.se:x.fi>y.fi;}};
priority_queue<PLL,vector<PLL>,cmp>Q;
LL ans,cnt; int main()
{
freopen("epic.in","r",stdin);
freopen("epic.out","w",stdout);
int i;
N=gint();K=gint();
re(i,,N)Q.push(PLL(gll(),));
while((N-)%(K-)!=)Q.push(PLL(,)),N++;
while(Q.size()!=)
{
PLL t=PLL(,);
re(i,,K){t.fi+=Q.top().fi;upmax(t.se,Q.top().se+);Q.pop();}
ans+=t.fi;
Q.push(t);
}
cout<<ans<<endl;
cout<<Q.top().se-<<endl;
return ;
}

D2T2

后缀数组+并查集。

这种问题好像经常遇到,至少看到过2次了,后缀数组一定要熟悉啊。

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<fstream>
#include<algorithm>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<utility>
#include<set>
#include<bitset>
#include<vector>
#include<functional>
#include<deque>
#include<cctype>
#include<climits>
#include<complex>
//#include<bits/stdc++.h>适用于CF,UOJ,但不适用于poj using namespace std; typedef long long LL;
typedef double DB;
typedef pair<int,int> PII;
typedef complex<DB> CP; #define mmst(a,v) memset(a,v,sizeof(a))
#define mmcy(a,b) memcpy(a,b,sizeof(a))
#define re(i,a,b) for(i=a;i<=b;i++)
#define red(i,a,b) for(i=a;i>=b;i--)
#define fi first
#define se second
#define m_p(a,b) make_pair(a,b)
#define SF scanf
#define PF printf
#define two(k) (1<<(k)) template<class T>inline T sqr(T x){return x*x;}
template<class T>inline void upmin(T &t,T tmp){if(t>tmp)t=tmp;}
template<class T>inline void upmax(T &t,T tmp){if(t<tmp)t=tmp;} const DB EPS=1e-;
inline int sgn(DB x){if(abs(x)<EPS)return ;return(x>)?:-;}
const DB Pi=acos(-1.0); inline int gint()
{
int res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
}
inline LL gll()
{
LL res=;bool neg=;char z;
for(z=getchar();z!=EOF && z!='-' && !isdigit(z);z=getchar());
if(z==EOF)return ;
if(z=='-'){neg=;z=getchar();}
for(;z!=EOF && isdigit(z);res=res*+z-'',z=getchar());
return (neg)?-res:res;
} const int maxN=;
const LL INF=1LL<<; int N;
char S[maxN+];
LL a[maxN+]; int r[maxN+],sa[maxN+],rank[maxN+],height[maxN+];
int table[maxN+],wa[maxN+],wb[maxN+];
inline bool cmp(int *r,int a,int b,int len){return r[a]==r[b] && r[a+len]==r[b+len];}
inline void da()
{
int i,j,k,p,*x=wa,*y=wb,tol;
re(i,,N)r[i]=S[i]-' '+;
p=;re(i,,N)upmax(p,x[i]=r[i]);
re(i,,p)table[i]=;
re(i,,N)table[x[i]]++;
re(i,,p)table[i]+=table[i-];
red(i,N,)sa[table[x[i]]--]=i;
for(swap(x,y),x[sa[]]=p=,i=;i<=N;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],)?p:++p;
for(j=;p<N;j*=)
{
tol=;
re(i,N-j+,N)y[++tol]=i;
re(i,,N)if(sa[i]-j>=)y[++tol]=sa[i]-j;
re(i,,p)table[i]=;
re(i,,N)table[x[y[i]]]++;
re(i,,p)table[i]+=table[i-];
red(i,N,)sa[table[x[y[i]]]--]=y[i];
for(swap(x,y),x[sa[]]=p=,i=;i<=N;i++)
x[sa[i]]=cmp(y,sa[i-],sa[i],j)?p:++p;
}
re(i,,N)rank[sa[i]]=i;
for(i=,j,k=;i<=N-;height[rank[i++]]=k)
for(k?k--:,j=sa[rank[i]-];r[i+k]==r[j+k];k++);
} LL ge,As;
LL ans1[maxN+],ans2[maxN+];
struct Tbak
{
int val,pos;
inline Tbak(int _val=,int _pos=){val=_val;pos=_pos;}
}bak[maxN+];int cnt;
inline bool cmpbak(Tbak a,Tbak b){return a.val>b.val;} PII route[maxN+];
LL o[maxN+],Q1[maxN+],Q2[maxN+],Q3[maxN+],Q4[maxN+];
/*
Q1 最大非负数
Q2 最小非负数
Q3 最大非正数
Q4 最小非正数
*/
int pa[maxN+];
inline int findroot(int a){return pa[a]<?a:pa[a]=findroot(pa[a]);} int main()
{
freopen("savour.in","r",stdin);
freopen("savour.out","w",stdout);
int i;
N=gint();
scanf("%s\n",S+);
re(i,,N)a[i]=gll();
S[++N]=' ';
da(); re(i,,N)o[rank[i]]=a[i];
re(i,,N)
{
pa[i]=-;
route[i]=PII(i,i);
if(o[i]>=) Q1[i]=o[i]; else Q1[i]=-INF;
if(o[i]>=) Q2[i]=o[i]; else Q2[i]=INF;
if(o[i]<=) Q3[i]=o[i]; else Q3[i]=-INF;
if(o[i]<=) Q4[i]=o[i]; else Q4[i]=INF;
} re(i,,N)bak[++cnt]=Tbak(height[i],i);
sort(bak+,bak+cnt+,cmpbak);
int head=;
ge=;As=-INF;
red(i,N-,)
{
while(head<=cnt && bak[head].val==i)
{
int f1=findroot(bak[head].pos-),f2=findroot(bak[head].pos);
PII D1=route[f1],D2=route[f2];
ge+=LL(D1.se-D1.fi+)*LL(D2.se-D2.fi+);
if(Q1[f1]!=-INF && Q1[f2]!=-INF) upmax(As,Q1[f1]*Q1[f2]);
if(Q4[f1]!=INF && Q4[f2]!=INF) upmax(As,Q4[f1]*Q4[f2]);
if(Q2[f1]!=INF && Q3[f2]!=-INF) upmax(As,Q2[f1]*Q3[f2]);
if(Q3[f1]!=-INF && Q2[f2]!=INF) upmax(As,Q3[f1]*Q2[f2]); if(pa[f1]>pa[f2])swap(f1,f2);
pa[f1]=pa[f1]+pa[f2];
pa[f2]=f1;
route[f1]=PII(D1.fi,D2.se);
upmax(Q1[f1],Q1[f2]);
upmin(Q2[f1],Q2[f2]);
upmax(Q3[f1],Q3[f2]);
upmin(Q4[f1],Q4[f2]); head++;
}
ans1[i]=ge;
ans2[i]=(ge==)?:As;
}
re(i,,N-)printf("%I64d %I64d\n",ans1[i],ans2[i]);
return ;
}

NOI2015的更多相关文章

  1. BZOJ 4199: [Noi2015]品酒大会 [后缀数组 带权并查集]

    4199: [Noi2015]品酒大会 UOJ:http://uoj.ac/problem/131 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品 ...

  2. BZOJ 4196: [Noi2015]软件包管理器 [树链剖分 DFS序]

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1352  Solved: 780[Submit][Stat ...

  3. [BZOJ4200][Noi2015]小园丁与老司机

    4200: [Noi2015]小园丁与老司机 Time Limit: 20 Sec  Memory Limit: 512 MBSec  Special JudgeSubmit: 106  Solved ...

  4. [BZOJ4199][NOI2015]品酒大会

    #131. [NOI2015]品酒大会 统计 描述 提交 自定义测试 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个奖项, ...

  5. [BZOJ4198][Noi2015]荷马史诗

    4198: [Noi2015]荷马史诗 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 700  Solved: 365[Submit][Status] ...

  6. [BZOJ4197][Noi2015]寿司晚宴

    4197: [Noi2015]寿司晚宴 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 412  Solved: 279[Submit][Status] ...

  7. [BZOJ4196][NOI2015]软件包管理器

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1040  Solved: 603[Submit][Stat ...

  8. NOI2015 题解

    [NOI2015]程序自动分析 离散化+并查集. [NOI2015]软件包管理器 [Noi2015]寿司晚宴 [Noi2015]荷马史诗 [NOI2015]品酒大会 [Noi2015]小园丁与老司机

  9. [UOJ#131][BZOJ4199][NOI2015]品酒大会 后缀数组 + 并查集

    [UOJ#131][BZOJ4199][NOI2015]品酒大会 试题描述 一年一度的“幻影阁夏日品酒大会”隆重开幕了.大会包含品尝和趣味挑战两个环节,分别向优胜者颁发“首席品酒家”和“首席猎手”两个 ...

  10. noi2015的回忆和教训

    前几天偶然打开了bzoj的rank list,突然发现——我竟然掉出了第一版!!! 自从我5月还是6月刷进第一版之后,我曾经天真的以为大概半年之内我还能保留在第一版内吧. 结果仅仅短短的4个月,我就已 ...

随机推荐

  1. HDFS文件系统的操作

    package com.bank.utils; import java.io.BufferedInputStream;import java.io.BufferedOutputStream;impor ...

  2. 多次绑定click及ajax提交常用方法

    <script> $(document).ready(function() { //绑定click $(".exchange_ecv").bind("clic ...

  3. bat文件调用shutdown命令不生效问题原因

    背景: 本人使用云桌面办公,但是用于登陆云桌面的终端运行卡顿,每次开机要20min才能登陆云桌面,所以: 1)在BIOS设置了定时开关,让终端提前开机 2)在系统上层,开机启动项增加一个bat文件(s ...

  4. J2EE基础总结(4)——JSP

    什么是JSP       JSP全名为Java Server Pages,中文名叫javaserver页面,其根本是一个简化的Servlet设计,它是由Sun  Microsystems公司倡导.很多 ...

  5. hadoop部署工具与配置工具

    https://github.com/xianglei/phpHiveAdmin 随着Hadoop的推出,大数据处理实现了技术上的落地.但是对于一般的公司和开发者而言,Hadoop依旧是一个陌生或者难 ...

  6. Shell-WEB目录监控

    #!/bin/sh #date:2015-12-08 #filename:check_webfile.sh #作者:李兴利 #Email:1162572407@qq.com #version:v1.1 ...

  7. (四)《Java编程思想》——可变参数列表

    以object数组为参数的方法实现可变参数列表 package chapter5; /** * 以object数组为参数的方法实现可变参数列表 */ class A { } public class ...

  8. JAVA--聊天界面面板

    package windows.beautify; import java.awt.BorderLayout; import java.awt.Color; import java.awt.event ...

  9. UITableVIewcell中图片不能改变大小的原因

    你有没没有发现,有时候把图片放进cell.imageView中时无法顺利改变大小呢? 其实根本原因是要在layoutSubviews重新配置一下,cell的布局里面默认有一个imageiView,同时 ...

  10. MySql中Blob二进制对象的处理

    BLOB (binary large object),二进制大对象,是一个可以存储二进制文件的容器. 可以用于存储图片等信息 Demo1:存储图片 String sql="INSERT IN ...