# NOI2015题解

D1T1：

D1T2：

D1T3：

D2T1：
$K=2$$K=2$时可以直接用huffman树做
$K\ne 2$$K\neq 2$时，若$n$$n$不满足$n-1\equiv 0\left(\phantom{\rule{0.667em}{0ex}}\mathrm{mod}\phantom{\rule{thinmathspace}{0ex}}\phantom{\rule{thinmathspace}{0ex}}K-1\right)$$n-1\equiv 0(\mod K-1)$，这棵树就不是满的k叉树，直接像huffman树那样做会错因为这样做树根的孩子不足k个，而把某些子树里的点提上来显然更优，于是我们补若干个权值为$0$$0$的虚点直到这棵树满

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 long
using namespace std;

inline void up(int &a,const int &b){if(a<b)a=b;}
const int maxn = 310000;

int n,K;
int l[maxn],cnt;
ll a[maxn],siz[maxn];
struct node
{
ll x;
int len,i;
friend inline bool operator <(const node x,const node y)
{
return x.x==y.x?x.len>y.len:x.x>y.x;
}
};
priority_queue<node>q;

int t[maxn],tp;
ll ans1; int ans2;
void Solve()
{
for(int i=1;i<=n;i++) q.push((node){siz[i]=a[i],l[i]=0,i});
cnt=n;

while(q.size()>1)
{
tp=0;
for(int j=1;j<=K&&!q.empty();j++)
{
const node now=q.top(); q.pop();
t[++tp]=now.i;
}
int mx=0;
for(int j=1;j<=tp;j++) up(mx,l[t[j]]);

++cnt,l[cnt]=mx+1;
for(int j=1;j<=tp;j++) siz[cnt]+=siz[t[j]];
ans1+=siz[cnt];

q.push((node){siz[cnt],l[cnt],cnt});
}
ans2=l[cnt];
}

int main()
{
//freopen("ex_epic3.in","r",stdin);
//freopen("tmp.out","w",stdout);

scanf("%d%d",&n,&K);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
while(K!=2&&n%(K-1)!=1) a[++n]=0;

Solve();
printf("%lld\n%d\n",ans1,ans2);

return 0;
}



D2T2：

SAM做法：把后缀树建出来好像可以直接乱搞

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 long
#define pb push_back
#define SZ(x) (int)x.size()
using namespace std;

{
char c; while(!((c=getchar())>='0'&&c<='9'));
x=c-'0';
while((c=getchar())>='0'&&c<='9') (x*=10)+=c-'0';
}
inline void down(int &a,const int &b){if(a>b)a=b;}
inline void up(int &a,const int &b){if(a<b)a=b;}
const int maxn = 610000;

int n;
int a[maxn];
int str[maxn];
int sa[maxn],rank[maxn],fir[maxn],sec[maxn];
int t[maxn];
void sort_(int str[],int re[],int rk[],int n,int m)
{
for(int i=0;i<=m;i++) t[i]=0;
for(int i=1;i<=n;i++) t[str[rk[i]]]++;
for(int i=1;i<=m;i++) t[i]+=t[i-1];
for(int i=n;i>=1;i--) re[t[str[rk[i]]]--]=rk[i];
}
void get_SA()
{
for(int i=1;i<=n;i++) rank[i]=i;
sort_(str,sa,rank,n,30);
rank[sa[1]]=1;
for(int i=2;i<=n;i++) rank[sa[i]]=rank[sa[i-1]]+(str[sa[i]]!=str[sa[i-1]]);
int t=1;
while(rank[sa[n]]!=n)
{
for(int i=1;i<=n;i++)
{
sa[i]=i;
fir[i]=rank[i],sec[i]=i+t>n?0:rank[i+t];
}
sort_(sec,rank,sa,n,n);
sort_(fir,sa,rank,n,n);
rank[sa[1]]=1;
for(int i=2;i<=n;i++) rank[sa[i]]=rank[sa[i-1]]+(fir[sa[i]]!=fir[sa[i-1]]||sec[sa[i]]!=sec[sa[i-1]]);
t<<=1;
}
}
int height[maxn];
void get_Height()
{
height[1]=0; int k=0;
for(int i=1;i<=n;i++)
{
if(k) k--;
if(rank[i]==1)continue;
while(str[i+k]==str[sa[rank[i]-1]+k]) k++;
height[rank[i]]=k;
}
}

vector<int>V[maxn];
int fa[maxn],mx[maxn],mn[maxn],siz[maxn];
int findfa(const int x){return fa[x]==x?x:fa[x]=findfa(fa[x]);}

ll ans[maxn],ans2[maxn];
char S[maxn];

int main()
{
//freopen("ex_savour2.in","r",stdin);
//freopen("tmp.out","w",stdout);

scanf("%s",S);
for(int i=1;i<=n;i++) str[i]=S[i-1]-'a'+1;
for(int i=1;i<=n;i++) scanf("%d",&a[i]);

get_SA();
get_Height();

for(int i=2;i<=n;i++) V[height[i]].pb(i);
for(int i=1;i<=n;i++) fa[i]=i,mx[i]=mn[i]=a[sa[i]],siz[i]=1;

ans2[n]=LLONG_MIN;
for(int i=n-1;i>=0;i--)
{
ans[i]=ans[i+1],ans2[i]=ans2[i+1];
for(int j=0;j<SZ(V[i]);j++)
{
int x=V[i][j];
int f1=findfa(x-1),f2=findfa(x);

ans[i]+=(ll)siz[f1]*siz[f2];
siz[f1]+=siz[f2];
ans2[i]=max(ans2[i],(ll)mx[f1]*mx[f2]);
ans2[i]=max(ans2[i],(ll)mn[f1]*mn[f2]);
up(mx[f1],mx[f2]);
down(mn[f1],mn[f2]);
fa[f2]=f1;
}
}

for(int i=0;i<n;i++) printf("%lld %lld\n",ans[i],ans2[i]==LLONG_MIN?0:ans2[i]);

return 0;
}



D2T3

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 long
#define pb push_back
#define mp make_pair
#define SZ(x) (int)x.size()
#define inf 1e9
using namespace std;

inline void up(int &a,const int &b){if(a<b)a=b;}
inline void down(int &a,const int &b){if(a>b)a=b;}
const int maxn = 210000;
const int maxm = maxn*12;

int n;
map<int,int>a,b,c,d; // x,y,x+y,x-y
int an,bn,cn,dn;
struct data
{
int x,i;
friend inline bool operator <(const data x,const data y){return x.x<y.x;}
}yi[maxn];
vector<data>va[maxn],vb[maxn],vc[maxn],vd[maxn];
struct point
{
int x,y;
int ia,ib,ic,id;
int ai,bi,ci,di;
}p[maxn];
vector<int>V[maxn],Vi[maxn];
void ins(int x,int y){ V[x].pb(y),Vi[y].pb(x); }
void build()
{
for(int i=0,tc,j;i<=n;i++)
{
tc=p[i].x; if(a.count(tc)==0) a[tc]=++an;
p[i].ia=j=a[tc]; va[j].pb((data){p[i].y,i});

tc=p[i].y; if(b.count(tc)==0) b[tc]=++bn;
p[i].ib=j=b[tc]; vb[j].pb((data){p[i].x,i});

tc=p[i].x+p[i].y; if(c.count(tc)==0) c[tc]=++cn;
p[i].ic=j=c[tc]; vc[j].pb((data){p[i].x,i});

tc=p[i].x-p[i].y; if(d.count(tc)==0) d[tc]=++dn;
p[i].id=j=d[tc]; vd[j].pb((data){p[i].x,i});
}

for(int i=1;i<=an;i++) sort(va[i].begin(),va[i].end());
for(int i=1;i<=bn;i++) sort(vb[i].begin(),vb[i].end());
for(int i=1;i<=cn;i++) sort(vc[i].begin(),vc[i].end());
for(int i=1;i<=dn;i++) sort(vd[i].begin(),vd[i].end());

for(int i=1;i<=an;i++) for(int j=0;j<SZ(va[i]);j++) p[va[i][j].i].ai=j;
for(int i=1;i<=bn;i++) for(int j=0;j<SZ(vb[i]);j++) p[vb[i][j].i].bi=j;
for(int i=1;i<=cn;i++) for(int j=0;j<SZ(vc[i]);j++) p[vc[i][j].i].ci=j;
for(int i=1;i<=dn;i++) for(int j=0;j<SZ(vd[i]);j++) p[vd[i][j].i].di=j;

for(int i=0,ii;i<=n;i++)
{
ii=p[i].ia; if(p[i].ai+1<SZ(va[ii])) ins(i,va[ii][p[i].ai+1].i);
ii=p[i].ic; if(p[i].ci) ins(i,vc[ii][p[i].ci-1].i);
ii=p[i].id; if(p[i].di+1<SZ(vd[ii])) ins(i,vd[ii][p[i].di+1].i);
}
}
int tf[maxn],f[maxn],pf[maxn],tg[maxn],g[maxn],mxlen;
void ANS1(int x)
{
mxlen=f[x];
printf("%d\n",mxlen-1);

int t[maxn],tp; t[tp=0]=-1;
while(x)
{
if(x<=n) t[++tp]=x;
else if(x-n!=t[tp]) t[++tp]=x-n;
if(!x)break;
if(x<=n)
{
int y=pf[x]-n;
if(p[y].bi<p[x].bi)
{
int i=p[y].bi,j=p[x].bi,now=p[x].ib;
for(int k=j-1;k>i;k--) t[++tp]=vb[now][k].i;
for(int k=0;k<i;k++) t[++tp]=vb[now][k].i;
}
else if(p[y].bi>p[x].bi)
{
int i=p[x].bi,j=p[y].bi,now=p[x].ib;
for(int k=i+1;k<j;k++) t[++tp]=vb[now][k].i;
for(int k=SZ(vb[now])-1;k>j;k--) t[++tp]=vb[now][k].i;
}
}
x=pf[x];
}
for(int i=tp;i>=1;i--) printf("%d%c",t[i],i==1?'\n':' ');
}
void DP()
{
for(int i=1;i<=bn;i++) yi[i]=(data){p[vb[i][0].i].y,i};
sort(yi+1,yi+bn+1);

for(int i=0;i<=n;i++) tf[i]=f[i]=-n*2;
tf[0]=1;
for(int ti=1;ti<=bn;ti++)
{
const int now=yi[ti].i;

int mxi=0;
for(int j=0;j<SZ(vb[now]);j++)
{
int i=vb[now][j].i;
f[i]=tf[i],pf[i]=n+i;
if(mxi&&tf[mxi]+j>f[i]) f[i]=tf[mxi]+j,pf[i]=n+mxi;
if(!mxi||tf[mxi]<tf[i]) mxi=i;
}
mxi=0;
for(int j=SZ(vb[now])-1;j>=0;j--)
{
int i=vb[now][j].i;
if(mxi&&tf[mxi]+SZ(vb[now])-1-j>f[i]) f[i]=tf[mxi]+SZ(vb[now])-1-j,pf[i]=n+mxi;
if(!mxi||tf[mxi]<tf[i]) mxi=i;
}

for(int j=0;j<SZ(vb[now]);j++)
{
int x=vb[now][j].i;
for(int i=0;i<SZ(V[x]);i++)
{
int y=V[x][i];
if(f[x]+1>tf[y]) tf[y]=f[x]+1,pf[n+y]=x;
}
}
}

int ansi=0; for(int i=0;i<=n;i++) if(f[i]>f[ansi]) ansi=i;
ANS1(ansi);

for(int i=0;i<=n;i++) tg[i]=1,g[i]=-n*2;
for(int ti=bn;ti>=1;ti--)
{
const int now=yi[ti].i;

int mxi=0;
for(int j=0;j<SZ(vb[now]);j++)
{
int i=vb[now][j].i;
g[i]=tg[i];
if(mxi) up(g[i],tg[mxi]+SZ(vb[now])-1-p[mxi].bi);
if(!mxi||tg[mxi]-p[mxi].bi<tg[i]-p[i].bi) mxi=i;
}
mxi=0;
for(int j=SZ(vb[now])-1;j>=0;j--)
{
int i=vb[now][j].i;
if(mxi) up(g[i],tg[mxi]+p[mxi].bi);
if(!mxi||tg[mxi]+p[mxi].bi<tg[i]+p[i].bi) mxi=i;
}

for(int j=0;j<SZ(vb[now]);j++)
{
int x=vb[now][j].i;
for(int i=0;i<SZ(Vi[x]);i++)
{
int y=Vi[x][i];
up(tg[y],g[x]+1);
}
}
}
}

namespace Graph
{
int s,t,ss,tt;
struct edge{int y,c,nex;}a[maxm]; int len,fir[maxn];
inline void ins(const int x,const int y,const int c)
{
a[++len]=(edge){y,c,fir[x]};fir[x]=len;
a[++len]=(edge){x,0,fir[y]};fir[y]=len;
}
int d[maxn],fullflow;
void init()
{
s=n+1,t=s+1,ss=t+1,tt=ss+1; len=1;
memset(fir,0,sizeof fir);

for(int x=0;x<=n;x++)
ins(s,x,inf),ins(x,t,inf);
for(int x=0;x<=n;x++) for(int i=0;i<SZ(V[x]);i++)
{
int y=V[x][i];
if(f[x]+g[y]==mxlen)
{
ins(x,y,inf);
d[x]++,d[y]--;
}
}
for(int x=0;x<=n;x++) if(d[x])
{
if(d[x]>0) ins(x,tt,d[x]);
else ins(ss,x,-d[x]),fullflow-=d[x];
}
}
int h[maxn],st,ed,ph[maxn];
queue<int>q;
bool bfs()
{
for(int i=0;i<=tt;i++) h[i]=0;
h[st]=1; q.push(st);
while(!q.empty())
{
const int x=q.front(); q.pop();
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y) if(a[k].c&&!h[y])
h[y]=h[x]+1,ph[y]=x,q.push(y);
}
return h[ed]>0;
}
int dfs(const int x,const int flow)
{
if(x==ed) return flow;
int delta=0;
for(int k=fir[x],y=a[k].y;k;k=a[k].nex,y=a[k].y)
{
if(a[k].c&&h[y]==h[x]+1)
{
int minc=dfs(y,min(a[k].c,flow-delta));
a[k].c-=minc,a[k^1].c+=minc;
delta+=minc;
}
if(delta==flow) return delta;
}
if(!delta) h[x]=0;
return delta;
}
int Flow()
{
int re=0;
while(bfs()) re+=dfs(st,inf);
return re;
}
int Solve()
{
st=ss,ed=tt;
return fullflow-Flow();
}
}

int main()
{
scanf("%d",&n);
p[0].x=p[0].y=0;
for(int i=1;i<=n;i++) scanf("%d%d",&p[i].x,&p[i].y);

build();
DP();

Graph::init();
printf("%d\n",Graph::Solve());

return 0;
}



• 评论

• 上一篇
• 下一篇