11.7 CSP赛前集训小结
今天是单赛日
1.上午的订正:没啥好说的
昨天的T1,稍微写下思路,维护高度差然后直接分情况讨论会很让人自闭,再加上符号+-和变化量的不同,会爆炸,那么不妨将之间的变化先减去,算上答案后再再加回来即可,正难则反的道理。
#include<stdio.h> #include<bits/stdc++.h> #define maxn 200005 using namespace std; long long Ht[maxn]; long long n,q,s,t; long long Getdel(long long x) { return x > 0 ? x * s : x * t; } long long T=0; int main() { scanf("%lld%lld%lld%lld",&n,&q,&s,&t); s=-s; t=-t; for(long long i=0;i<=n;i++) scanf("%lld",&Ht[i]); for(long long i=n;i;i--) Ht[i]-=Ht[i-1]; for(long long i=1;i<=n;i++) T+=Getdel(Ht[i]); long long x,y; long long temp; while(q--) { scanf("%lld%lld%lld",&x,&y,&temp); T-=Getdel(Ht[x]); T-=Getdel(Ht[y+1]); Ht[x]+=temp; if(y+1<=n) Ht[y+1]-=temp; T+=Getdel(Ht[x]); if(y+1<=n) T+=Getdel(Ht[y+1]); printf("%lld\n",T); } }
然后就是董神讲的两道题,一道是再求最短路时DP一下,另一道则是口胡了一堆破数学公式。。然后发现题目看错了233333333
第一道的代码(本人没调,这是LCFjulao的代码)
#include<stdio.h> #include<queue> using namespace std; #define INF 1000000000 int End[100005],Next[100005],Len[100005],Last[10004],tot; int n,k,Dis[10004][12]; bool Inqueue[10005][12]; struct node{int p,t;}; bool operator<(node a,node b){return Dis[a.p][a.t]>Dis[b.p][b.t];} priority_queue<node>q; void Link(int x,int y,int l) { tot++; End[tot]=y; Len[tot]=l; Next[tot]=Last[x]; Last[x]=tot; } void DJ(int x) { int i,j,t,y; node a; for(i=0;i<=n;i++)for(j=0;j<=k;j++)Dis[i][j]=INF; Dis[x][0]=0; a.p=x,a.t=0; q.push(a); Inqueue[x][0]=true; while(q.size()) { x=q.top().p,t=q.top().t; q.pop(); Inqueue[x][t]=false; for(i=Last[x];i;i=Next[i]) { y=End[i]; if(Dis[x][t]+Len[i]<=Dis[y][t]) { Dis[y][t]=Dis[x][t]+Len[i]; if(!Inqueue[y][t]) { a.p=y,a.t=t; q.push(a); Inqueue[y][t]=true; } } if(t<k&&Dis[x][t]<Dis[y][t+1]) { Dis[y][t+1]=Dis[x][t]; if(!Inqueue[y][t+1]) { a.p=y,a.t=t+1; q.push(a); Inqueue[y][t+1]=true; } } } } } int main() { int m,s,t,a,b,c,i,ans=INF; scanf("%d %d %d",&n,&m,&k); scanf("%d %d",&s,&t); for(i=1;i<=m;i++) { scanf("%d %d %d",&a,&b,&c); Link(a,b,c); Link(b,a,c); } DJ(s); for(i=0;i<=k;i++)ans=min(ans,Dis[t][i]); printf("%d",ans); }
然后没事干,然后就水了道树DP的题(本来该用DP做的)
#include<bits/stdc++.h> #define maxn 10005 #define inf 999999999 using namespace std; /* 结论:树上任意一点的最长距离一定是到直径某一端点的距离 因此此题可以先通过该结论求出树的直径 求法:找任意一个点求出该点的最远距离点T 由结论可知T一定是树直径的端点,再求离T最远的点S,由结论又可知S也是端点 所以ST即为树的直径,然后再用一遍结论,本题中每个点的最远距离即为max(dis【S】,dis【T】); 要用到两次结论做本题,有点意思 */ struct node { int To,Len; }; vector<node> Map[maxn]; int Max_Dis=-inf; int S=0; int Type=0; int Dis_S[maxn]; int Dis_T[maxn]; void Dfs1(int pos,int fa,int Dis) { // cout<<Dis<<endl; if(Type==1) { Dis_S[pos]=Dis; } if(Type==2) { Dis_T[pos]=Dis; } if(Dis>=Max_Dis) { S=pos; Max_Dis=Dis; } for(int i=0;i<Map[pos].size();i++) { if(Map[pos][i].To!=fa) Dfs1(Map[pos][i].To,pos,Dis+Map[pos][i].Len); } } int main() { int n; scanf("%d",&n); node temp; int x,y; for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); temp.To=x; temp.Len=y; Map[i+1].push_back(temp); temp.To=i+1; Map[x].push_back(temp); } Type=0; Dfs1(1,1,0); int SS=S; Max_Dis=-inf; S=0; Type=1; Dfs1(SS,SS,0); int TT=S; Type=2; Max_Dis=-inf; Dfs1(TT,TT,0); for(int i=1;i<=n;i++) { printf("%d\n",max(Dis_T[i],Dis_S[i])); } }
原文地址:https://www.cnblogs.com/pveds/p/11811306.html
时间: 2024-10-08 08:54:39