D1T1:模拟不解释
D1T2:最难一题(真心不科学),考场上写了个nlog2n算法,当时还天真地以为只有一个log(手动滑稽),然而内存没开够(虽然官方数据似乎还是95)。
不过miaom大一眼帮我改到nlogn,说实话感觉比标解好理解多了。
首先树链剖分一发。然后起点到终点的路径就被pou成了logn段,这时就想着把这一段的时间(显然是一个+1/-1等差数列)变成一个数,然后我想的是把他们的时间全部减去他们的dfn序号(-1的就反过来,可以自己yy一下),然后就将操作变成了在[l,r]这段上将权值为k的每一个数值加1(数值不是权值),然后差分一下,最后乱搞前缀和就行了。。。
#include <iostream>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#define gc getchar()
#define N 1000059
#define mid (l+r>>1)
#define pa pair<int,int>
using namespace std;
int n,m,first[N],number=0,x,y,w[N],s[N],t[N],cnt=0,Cnt=0;
int father[N],size[N],Mson[N],deep[N],dfn[N],top[N],Id[N];
int ans[N],aaa[N][2],val[N][2];
vector<pa> an[N][2];
struct edge
{
int to,next;
void add(int x,int y)
{
to=y,next=first[x],first[x]=number;
}
}e[N<<1];
int read()
{
int x=1;
char ch;
while (ch=gc,ch>'9'||ch<'0') if (ch=='-') x=-1;
int s=ch-48;
while (ch=gc,ch>='0'&&ch<='9') s=s*10+ch-48;
return s*x;
}
void dfs1(int x)
{
size[x]=1;
deep[x]=deep[father[x]]+1;
for (int i=first[x];i;i=e[i].next)
if (e[i].to!=father[x])
{
father[e[i].to]=x;
dfs1(e[i].to);
size[x]+=size[e[i].to];
if (size[e[i].to]>size[Mson[x]]) Mson[x]=e[i].to;
}
}
void dfs2(int x,int y)
{
top[x]=y;
dfn[x]=++cnt;
Id[cnt]=x;
if (Mson[x]) dfs2(Mson[x],y);
for (int i=first[x];i;i=e[i].next)
if (e[i].to!=father[x]&&e[i].to!=Mson[x])
dfs2(e[i].to,e[i].to);
}
int lca(int x,int y)
{
for (;top[x]!=top[y];x=father[top[x]])
if (deep[top[x]]<deep[top[y]]) swap(x,y);
return deep[x]<deep[y]?x:y;
}
int get_dis(int x,int y)
{
return deep[x]+deep[y]-2*deep[lca(x,y)];
}
void ins(int l,int r,int val,int k)
{
an[l][k].push_back(make_pair(val,1));
an[r+1][k].push_back(make_pair(val,-1));
}
void ins(int x,int y)
{
int pd=1;
int st=0;
int dis=get_dis(x,y);
for (;top[x]!=top[y];x=father[top[x]])
{
if (deep[top[x]]<deep[top[y]]) swap(x,y),pd^=1;
if (pd==1)
{
ins(dfn[top[x]],dfn[x],st+dfn[x]-1,1);
st+=dfn[x]-dfn[top[x]]+1;
}
else
{
ins(dfn[top[x]],dfn[x],dis-dfn[x]+n,0);
dis-=(dfn[x]-dfn[top[x]])+1;
}
}
if (dfn[x]>dfn[y]) swap(x,y),pd^=1;
if (pd==1)
ins(dfn[x],dfn[y],st-dfn[x]+n,0);
else
ins(dfn[x],dfn[y],st+dfn[y]-1,1);
}
int main()
{
n=read(),m=read();
for (int i=1;i<n;i++)
{
x=read(),y=read();
e[++number].add(x,y);
e[++number].add(y,x);
}
father[1]=deep[0]=0;
dfs1(1);
dfs2(1,1);
for (int i=1;i<=n;i++)
w[i]=read();
for (int i=1;i<=m;i++)
{
s[i]=read(),t[i]=read();
ins(s[i],t[i]);
}
for (int l=1;l<=n;l++)
{
val[l][0]=w[Id[l]]-l+n;
val[l][1]=w[Id[l]]+l-1;
}
memset(aaa,0,sizeof(aaa));
for (int i=1;i<=n;i++)
{
for (int k=0;k<2;k++)
for (int j=0;j<an[i][k].size();j++)
aaa[an[i][k][j].first][k]+=an[i][k][j].second;
ans[Id[i]]=aaa[val[i][0]][0]+aaa[val[i][1]][1];
}
for (int i=1;i<=n;i++)
printf("%d%s",ans[i],i==n?"\n":" ");
return 0;
}
D1T3:斯波的期望打牌(dp),然后我忘了初始化了,始化了,化了,了,。。。。
dp[i][j][k]表示第i个教室是否申请,然后总共申请了k次的期望路径值。。。
D2T1:这都能炸,感觉人生没有希望。。预处理出2000*2000的c值(杨辉三角),然后二维前缀和一发
D2T2:看出来单调性后本题也变成了斯波题。。每条蚯蚓增加,相当于没有加的两条(刚断的)减去增加量。然后三个单调队列搞一搞,常数注意一下就行
D3T3:Tn2^ndp或者传说中的暴力dfs就能过,n^3预处理出选择两只猪后能打到哪些猪(状态压缩),然后状压dp一发就OK。。
似乎只有D1T2可以说一下。。然而一片斯波错误。。轻易滚粗。。