toy ——4130
思路:强模拟…
running ——4131
思路:暴力分还是挺多的,s=t,w=0,s=1,t=1,list时,满打满算还有80分,但功底还是差了点啊,实际上s=1,t=1时,暴力会超时,也就是说必须要用正解了。
仔细理解题意,一个玩家从a 到 b, 沿途到达点的时间为0,1,2,…,b-a,而每个点的观察员只在wi时观察,也就是说,若想要被观察员观察到,就必须是
wi+i 或 wi-i,那么这个就有点像树上差分了。
#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define INF 0x3f3f3f3f
#define N 300005
using namespace std;
int n,m;
struct node{
int s,t,lca,dis;
}A[N];
vector<int>E[N],vis[N];
int w[N],ans[N],sum[N];
int D[N],fa[N],top[N],sz[N],son[N];
struct p1{
void solve(){
REP(i,1,m)ans[A[i].s]++;
REP(i,1,n)printf("%d ",w[i]?0:ans[i]);
puts("");
}
}p1;
struct p2{
int sum1[N],sum2[N];
vector<int>vis1[N],vis2[N];
void solve(){
REP(i,1,m){
int a=A[i].s,b=A[i].t;
if (a<=b){
vis1[a].push_back(i);
vis1[b+1].push_back(i);
}else{
vis2[b].push_back(i);
vis2[a+1].push_back(i);
}
}
REP(i,1,n){
REP(j,0,vis1[i].size()-1){
int k=vis1[i][j];
if (A[k].s==i)sum1[A[k].s]++;
else sum1[A[k].s]--;
}
REP(j,0,vis2[i].size()-1){
int k=vis2[i][j];
if (A[k].t==i)sum2[A[k].s]++;
else sum2[A[k].s]--;
}
if (i-w[i]>=1) ans[i]+=sum1[i-w[i]];
if (i+w[i]<=n) ans[i]+=sum2[i+w[i]];
}
REP(i,1,n-1)printf("%d ",ans[i]);
printf("%d\n",ans[n]);
}
}p2;
struct p3{
void dfs(int x,int f){
D[x]=D[f]+1;
if(D[x]-w[x]>0)ans[x]-=sum[D[x]-w[x]];
REP(i,0,E[x].size()-1){
int y=E[x][i];
if(y==f)continue;
dfs(y,x);
}
REP(i,0,vis[x].size()-1)sum[A[vis[x][i]].s]++;
if(D[x]-w[x]>0)ans[x]+=sum[D[x]-w[x]];
}
void solve(){
REP(i,1,m)vis[A[i].t].push_back(i);
dfs(1,0);
REP(i,1,n)printf("%d ",ans[i]);
puts("");
}
}p3;
struct p4{
void dfs(int x,int f){
D[x]=D[f]+1;
if (D[x]+w[x]<=n) ans[x]-=sum[D[x]+w[x]];
REP(i,0,E[x].size()-1){
int to=E[x][i];
if (to==f) continue;
dfs(to,x);
}
for (int i=0;i<(int)vis[x].size();i++)sum[D[A[vis[x][i]].s]]++;
if (D[x]+w[x]<=n)ans[x]+=sum[D[x]+w[x]];
}
void solve(){
REP(i,1,m)vis[A[i].s].push_back(i);
dfs(1,0);
REP(i,1,n)printf("%d ",ans[i]);
puts("");
}
}p4;
struct p5{
struct Node{
int op,dep;
};
vector<Node>Q1[N],Q2[N];
int sum1[N],sum2[N*2];
void dfs1(int x,int f){
D[x]=D[f]+1;
fa[x]=f;
sz[x]=1;
REP(i,0,E[x].size()-1){
int y=E[x][i];
if(y==f)continue;
dfs1(y,x);
sz[x]+=sz[y];
if(sz[y]>sz[son[x]])son[x]=y;
}
}
void dfs2(int x,int tp){
top[x]=tp;
if(son[x])dfs2(son[x],tp);
REP(i,0,E[x].size()-1){
int y=E[x][i];
if(y==fa[x] || y==son[x])continue;
dfs2(y,y);
}
}
int Lca(int a,int b){
while(top[a]!=top[b]){
if(D[top[a]]<D[top[b]])swap(a,b);
a=fa[top[a]];
}
return D[a]<D[b]?a:b;
}
void dfs(int x,int f){
if(D[x]+w[x]<=n)ans[x]-=sum1[D[x]+w[x]];
ans[x]-=sum2[D[x]-w[x]+N];
REP(i,0,E[x].size()-1){
int y=E[x][i];
if(y==f)continue;
dfs(y,x);
}
REP(i,0,Q1[x].size()-1){
Node y=Q1[x][i];
if(y.op)sum1[y.dep]++;
else sum1[y.dep]--;
}
REP(i,0,Q2[x].size()-1){
Node y=Q2[x][i];
if(y.op)sum2[y.dep]++;
else sum2[y.dep]--;
}
if(D[x]+w[x]<=n)ans[x]+=sum1[D[x]+w[x]];
ans[x]+=sum2[D[x]-w[x]+N];
}
void solve(){
dfs1(1,0);
dfs2(1,1);
REP(i,1,m){
A[i].lca=Lca(A[i].s,A[i].t);
A[i].dis=D[A[i].s]+D[A[i].t]-D[A[i].lca]*2;
Q1[A[i].s].push_back((Node){1,D[A[i].s]});
Q1[A[i].lca].push_back((Node){0,D[A[i].s]});
Q2[A[i].t].push_back((Node){1,D[A[i].t]-A[i].dis+N});
Q2[fa[A[i].lca]].push_back((Node){0,D[A[i].t]-A[i].dis+N});
}
dfs(1,0);
REP(i,1,n)printf("%d ",ans[i]);
puts("");
}
}p5;
int main(){
// freopen("running.in","r",stdin);
// freopen("running.out","w",stdout);
cin>>n>>m;
REP(i,1,n-1){
int a,b;
scanf("%d%d",&a,&b);
E[a].push_back(b);
E[b].push_back(a);
}
REP(i,1,n)scanf("%d",&w[i]);
REP(i,1,m)scanf("%d%d",&A[i].s,&A[i].t);
if(n==991 || n==992)p1.solve();// s=t w=0
else if(n==99994)p2.solve();// list
else if(n==99995)p3.solve();// s=1
else if(n==99996)p4.solve();// t=1
else p5.solve(); // ac code
return 0;
}
classroom ——4132
思路:这题的暴力分也不少…,m=0,1,2时,满打满算也有68分(不赘述了),而正解显然是dp,但这里是期望dp。
#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define db double
#define N 2005
using namespace std;
int n,m,v,e;
int c[N],d[N];
db INF,p[N],dis[N][N],dp[N][N][2],ans;
void Floyd(){
REP(k,1,v)
REP(i,1,v)
REP(j,1,v)
dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);
}
struct p2{
void solve(){
db tot=1e15;
REP(k,1,n){
db sum=0;
db p1=1-p[k];
swap(c[k],d[k]);
REP(i,2,n)sum+=dis[c[i-1]][c[i]];
tot=min(tot,sum*p[k]+ans*p1);
swap(c[k],d[k]);
}
printf("%.2lf\n",tot);
}
}p2;
struct p3{
void solve(){
db tot=1e15;
REP(k,1,n){
REP(l,k+1,n){
db sum=0,res=0;
db p1=p[k]*p[l];
db p2=p[k]*(1-p[l]);
db p3=p[l]*(1-p[k]);
db p4=1-p1-p2-p3;
sum+=ans*p4;
swap(c[k],d[k]);
res=0;
REP(i,2,n)res+=dis[c[i-1]][c[i]];
sum+=res*p2;
swap(c[k],d[k]);
swap(c[l],d[l]);
res=0;
REP(i,2,n)res+=dis[c[i-1]][c[i]];
sum+=res*p3;
swap(c[l],d[l]);
swap(c[k],d[k]);swap(c[l],d[l]);
res=0;
REP(i,2,n)res+=dis[c[i-1]][c[i]];
sum+=res*p1;
swap(c[k],d[k]);swap(c[l],d[l]);
tot=min(tot,sum);
}
}
printf("%.2lf\n",tot);
}
}p3;
struct pAC{
void solve(){
memset(dp,127,sizeof(dp));
dp[1][0][0]=dp[1][1][1]=0;
REP(i,1,n-1)
REP(j,0,min(i,m)){
if(dp[i][j][0]!=INF){
dp[i+1][j][0]=min(dp[i+1][j][0],dp[i][j][0]+dis[c[i]][c[i+1]]);
if (j<m)dp[i+1][j+1][1]=min(dp[i+1][j+1][1],dp[i][j][0]+dis[c[i]][c[i+1]]*(1-p[i+1])+dis[c[i]][d[i+1]]*p[i+1]);
}
if(dp[i][j][1]!=INF){
dp[i+1][j][0]=min(dp[i+1][j][0],dp[i][j][1]+dis[c[i]][c[i+1]]*(1-p[i])+dis[d[i]][c[i+1]]*p[i]);
if (j<m) dp[i+1][j+1][1]=min(dp[i+1][j+1][1],
dp[i][j][1]+(1-p[i])*(1-p[i+1])*dis[c[i]][c[i+1]]+(1-p[i])*p[i+1]*dis[c[i]][d[i+1]]+p[i]*(1-p[i+1])*dis[d[i]][c[i+1]]+p[i]*p[i+1]*dis[d[i]][d[i+1]]);
}
}
REP(i,0,m)ans=min(ans,min(dp[n][i][0],dp[n][i][1]));
printf("%0.2lf\n",ans);
}
}p100;
int main(){
// freopen("classroom.in","r",stdin);
// freopen("classroom.out","w",stdout);
scanf("%d%d%d%d",&n,&m,&v,&e);
REP(i,1,n)scanf("%d",&c[i]);
REP(i,1,n)scanf("%d",&d[i]);
REP(i,1,n)scanf("%lf",&p[i]);
memset(dis,127,sizeof(dis));
INF=dis[0][0];
REP(i,1,v)dis[i][i]=0;
REP(i,1,e){
int x,y;
db z;
scanf("%d%d%lf",&x,&y,&z);
dis[x][y]=dis[y][x]=min(dis[x][y],z);
}
Floyd();
REP(i,2,n)ans+=dis[c[i-1]][c[i]];
if(!m)printf("%.2lf\n",ans);
else if(m==1)p2.solve();
else if(m==2 && n<10)p3.solve();
else p100.solve();
}
小结:去年的暴力分真心是多,100+35+68=203,而其中第2题s=1,t=1稍微想想应该也就有45…看来代码的功底还有待提高呀…