T1:听说很简单然后我biubiu了
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;j++)
#define N 100005
using namespace std;
char s[N][15];
int a[N],n,T;
int main(){
scanf("%d%d",&n,&T);
rep(i,0,n-1) scanf("%d%s",&a[i],s[i]);
int nw=0;
while (T--){
int k,l;
scanf("%d%d",&k,&l);
k=k^a[nw];
if (k==0){
nw-=l;
while (nw<0) nw+=n;
}else{
nw+=l;
while (nw>=n) nw-=n; //开始biubiu于等号没写(我听说if比%要快然后就233
}
}
puts(s[nw]);
return 0;
}
T2:把每一条路拆成朝上走的和朝下走的
发现朝上走的路径上的每一个点=经过的时间和深度的和不变
(每往上一格深度-1时间+1)
发现朝下走的路径上的每一个点=经过的时间和深度的差不变
(每往上一格深度-1时间-1)
问题就变成了一个点子树里标号为一个固定值的点的数量
所以在两条路头加加尾减减一遍dfs求解
易得答案就是刚刚遍历到此点和此点遍历所有子树之后的差(相当于多遍历了他的子树
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;j++)
#define N 300005
using namespace std;
int n,m,cnt,cnp,fa[N],deep[N],st[N],to[2*N],ne[2*N],sz[N],son[N],top[N],ans[N],ck[N];
int To[4*N],Ne[4*N],St[N],Sm[4*N],poi[2*N+5],TO[4*N],NE[4*N],ST[N],SM[4*N],Poi[2*N+5];
void add(int k,int l){
to[++cnt]=l;
ne[cnt]=st[k];
st[k]=cnt;
}
void dfs1(int k,int ff){
fa[k]=ff;
deep[k]=deep[ff]+1;
sz[k]=1;
int _=0,__=0;
for (int i=st[k];i;i=ne[i])
if (to[i]!=ff){
dfs1(to[i],k);
sz[k]+=sz[to[i]];
if (sz[to[i]]>__){
__=sz[to[i]];
_=to[i];
}
}
son[k]=_;
}
void dfs2(int k,bool lych){
if (lych) top[k]=top[fa[k]];
else top[k]=k;
if (son[k]) dfs2(son[k],1);
for (int i=st[k];i;i=ne[i])
if (to[i]!=fa[k]&&to[i]!=son[k])
dfs2(to[i],0);
}
int lca(int x,int y){
for (;top[x]!=top[y];x=fa[top[x]])
if (deep[top[x]]<deep[top[y]]) swap(x,y);
if (deep[x]<deep[y]) swap(x,y);
return y;
}
void ad(int k,int p,int l){
To[++cnt]=p;
Sm[cnt]=l;
Ne[cnt]=St[k];
St[k]=cnt;
}
void AD(int k,int p,int l){
TO[++cnp]=p;
SM[cnp]=l;
NE[cnp]=ST[k];
ST[k]=cnp;
}
void dfs(int k){
int qs=poi[deep[k]+ck[k]],QS=Poi[deep[k]-ck[k]+N];
for (int i=st[k];i;i=ne[i])
if (to[i]!=fa[k]) dfs(to[i]);
for (int i=St[k];i;i=Ne[i])
poi[To[i]]+=max(0,Sm[i]);
for (int i=ST[k];i;i=NE[i])
Poi[TO[i]]+=max(0,SM[i]);
ans[k]+=poi[deep[k]+ck[k]]+Poi[deep[k]-ck[k]+N]-qs-QS;
for (int i=St[k];i;i=Ne[i])
poi[To[i]]+=min(0,Sm[i]);
for (int i=ST[k];i;i=NE[i])
Poi[TO[i]]+=min(0,SM[i]);
}
int main(){
scanf("%d%d",&n,&m);
rep(i,1,n-1){
int k,l;
scanf("%d%d",&k,&l);
add(k,l);add(l,k);
}
rep(i,1,n) scanf("%d",&ck[i]);
dfs1(1,1);dfs2(1,0);
cnt=0;cnp=0;
rep(i,1,m){
int k,l;
scanf("%d%d",&k,&l);
int p=lca(k,l);
ad(k,deep[k],1);
ad(p,deep[k],-1); //向上的路径
AD(l,deep[l]-(deep[l]+deep[k]-2*deep[p])+N,1);
AD(p,deep[l]-(deep[l]+deep[k]-2*deep[p])+N,-1); //向下的路径
if (deep[k]==deep[p]+ck[p]) ans[p]--;//,printf("ok\n"); //节点会被记两次要-1
}
dfs(1);
rep(i,1,n-1) printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
T3:学会新技能:眼睛看不调试调程序
f[i][k][j]表示到第i个点申请j个教室
k=0表示该教室不申请k=1表示该教室申请
转移方程见程序
考场上居然忘了有floyd这种东西n遍spfa神清气爽
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(j,k,l) for (int j=k;j<=l;j++)
#define N 305
#define M 2005
#define K 90005
#define inf 10000000
using namespace std;
int n,m,v,e,a[M],b[M];
double f[M][2][M],rd[N][N],c[M];
void FLOYD(){
rep(k,1,v) rep(i,1,v) rep(j,1,v)
if (rd[i][k]<inf&&rd[k][j]<inf&&
rd[i][j]>rd[i][k]+rd[k][j])
rd[i][j]=rd[i][k]+rd[k][j];
}
int main(){
scanf("%d%d%d%d",&n,&m,&v,&e);
rep(i,1,n) scanf("%d",&a[i]);
rep(i,1,n) scanf("%d",&b[i]);
rep(i,1,n) scanf("%lf",&c[i]);
rep(i,1,v) rep(j,1,v) rd[i][j]=inf;
rep(i,1,v) rd[i][i]=0;
rep(i,1,e){
int k,l,p;
scanf("%d%d%d",&k,&l,&p);
if (rd[k][l]>p) rd[k][l]=p,rd[l][k]=p;
}
FLOYD();
rep(i,1,n) rep(j,0,1) rep(k,0,m) f[i][j][k]=-1;
f[1][0][0]=0;f[1][1][1]=0;//编号--是否申请--已申请数
rep(i,1,n-1){
rep(j,0,m){
if (f[i][0][j]>=0){
double cl;
cl=f[i][0][j]+rd[a[i]][a[i+1]];
if (f[i+1][0][j]==-1||f[i+1][0][j]>cl)
f[i+1][0][j]=cl;
cl=f[i][0][j]+rd[a[i]][a[i+1]]*(1-c[i+1])+rd[a[i]][b[i+1]]*c[i+1];
if (f[i+1][1][j+1]==-1||f[i+1][1][j+1]>cl)
f[i+1][1][j+1]=cl;
}
if (f[i][1][j]>=0){
double cl;
cl=f[i][1][j]+rd[a[i]][a[i+1]]*(1-c[i])+rd[b[i]][a[i+1]]*c[i];
if (f[i+1][0][j]==-1||f[i+1][0][j]>cl)
f[i+1][0][j]=cl;
cl=f[i][1][j]+rd[a[i]][a[i+1]]*(1-c[i])*(1-c[i+1])+rd[a[i]][b[i+1]]*(1-c[i])*c[i+1]+rd[b[i]][a[i+1]]*c[i]*(1-c[i+1])+rd[b[i]][b[i+1]]*c[i]*c[i+1];
if (f[i+1][1][j+1]==-1||f[i+1][1][j+1]>cl)
f[i+1][1][j+1]=cl;
}
}
}
double ans=2000000000;
rep(i,0,m) rep(j,0,1) if (f[n][j][i]<ans&&f[n][j][i]!=-1) ans=f[n][j][i];
printf("%.2f\n",ans);
}