2022HDU多校第四场
2022/7/30 6:25:04
本文主要是介绍2022HDU多校第四场,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
2022HDU多校第四场
过程
三题签到完成,吉吉在看了11一会后将01秒了,这里是我dp不够熟练,只能让吉吉来了,我好菜呀(哭),然后就坐牢开始了,我们轮流卡02和11,最后4题结束,惨淡收场。02属于是没想明白,另外时间不够,而11属实是坐大牢,看着它被人过穿,我们却毫无头绪,再一次在签到题上卡了太多时间,属实输麻了。赛后经人点拨,发现\(xor(l,r)\)如果\(l=r\)那么会变成0,那么题意就变成了求数组内异同或最大值,成了线性基板题,我哭死,再一次演了队友,下次不敢也不能在演了,队友要把我吃了。
题解
04
输出No即可
06
阅读理解题,理解题意后即可过,但这里我没想到\(1e6\)的\(cin\)读入\(double\)类型\(tle\)了,改成\(scanf\)就过了
07
因为所有的怪都要打过,假设当前位置为\(l\),那么每次一定是跳到一个位置\(r\),按照从\(r\)到\(l\)的方式依次将所有怪打过,再从\(r+1\)开始,因此我们设置一个当前所需能打过区间内所有怪的值,\(tmp=max(tmp-a[i],a[i])\),当我们的能力值大于这一值时,便可将这一区间所有怪打过,获得它们的生命值,当这个区间长度大于k时或者打不完怪时,输出\("NO"\)
void solve(){ cin>>n>>a[0]>>k; ll sum=a[0]; int dis=0,pos; bool flag=1; ll tmp=0,tep=0; rep(i,1,n){ a[i]=read(); if(!tmp) tmp=a[i],pos=i; else tmp=max(tmp-a[i],a[i]); //想要将整个区间怪打过所需最小的战力 dis++; tep+=a[i];//区间累计可获得战力和 if(dis>k) flag=0; if(sum>=tmp) {tmp=0;sum+=tep;tep=0;dis=0;} } if(dis) flag=0; if(flag) puts("YES"); else puts("NO"); }
11
注意到可以把一些位置变为0,那么可以等价为n个数中的异或最大值,套用线性基。
关于线性基此处应该再强化认识一下。
int n; ll d[60]; void insert(ll x){ rpe(i,50,0){ if(x&(1LL<<i)){ if(d[i]) x^=d[i]; else { d[i]=x;break; } } } } void solve(){ cin>>n; rep(i,0,50) d[i]=0; rep(i,1,n){ ll tmp;scanf("%lld",&tmp); insert(tmp); } ll ans=0; rpe(i,50,0){ if((ans^d[i])>ans) ans^=d[i]; } printf("%lld\n",ans); }
01
一眼区间DP,但我DP实在是做少了,属于是弱项了。
首先\(n\)必须是偶数,\(n\)为奇数直接输出\(0\)。
令\(dp[i][j]\)表示区间\([i,j]\)内可行的匹配数,首先枚举区间长度,然后枚举起点,得到终点,然后枚举区间断点,此时转移方程\(dp[i][j]=dp[i+1][mid-1]*dp[mid+1][j]*check(i,j)的求和\),即区间\([i+1,mid-1]\)和区间\([mid+1,j]\)可行的匹配个数与\((i,mid)\)是否能匹配的乘积,这里判断\((i,j)\)是否能匹配是个需要注意的点,一定是正数在前,负数在后。
int n,m; ll dp[maxn][maxn]; int a[maxn]; int gett(int i,int j){//i和j搭配的方法数 if(i+j==0) { if(i==j) return m; else if(i>0) return 1; else return 0; } else{ if(i==0&&j<0) return 1; else if(i>0&&j==0) return 1; return 0; } } void solve(){ cin>>n>>m; rep(i,1,n) scanf("%d",&a[i]); if(n&1) {puts("0");return;} rep(i,1,n) rep(j,1,n) dp[i][j]=0; for(int len=2;len<=n;len+=2){ rep(i,1,n){ int j=i+len-1; if(j>n) break; for(int mid=i+1;mid<=j;mid+=2){ ll z,b,c; if(mid>i+1) z=dp[i+1][mid-1]; else z=1; if(mid<j) b=dp[mid+1][j]; else b=1; c=gett(a[i],a[mid]); dp[i][j]=(dp[i][j] + z*b%mod*c%mod)%mod; } } } printf("%lld\n",dp[1][n]%mod); }
02
本题直接跑dijkstra是错误的,因为存在0环,即路程和奖励都为0,因此正确步骤为建立出最短路图,在最短路图中进行缩点去除0环,然后跑最长路得到最大奖励,这里直接记忆化搜索。
struct Dijkstra{ bool vis[maxn]; ll dis[maxn]; struct node{ ll dis;int id; bool operator < (const node &a)const{ return dis>a.dis; } }; priority_queue<node>q; vector<P>G[maxn]; void add(int u,int v,int w){ G[u].pb({v,w}); } inline void clear(int n){rep(i,1,n) G[i].clear();} void Dijk(int st,int n){ while(!q.empty()) q.pop(); rep(i,1,n) vis[i]=0,dis[i]=linf; dis[st]=0; q.push((node){0,st}); while(!q.empty()){ int u=q.top().id;q.pop(); if(vis[u]) continue; vis[u]=1; for(auto x:G[u]){ int w=x.second,v=x.first; if(dis[v]>dis[u]+w){ dis[v]=dis[u]+w; q.push((node){dis[v],v}); } } } } }D1,D2; struct Tarjan{ int dfn[maxn],low[maxn],timee=0; int scc_cnt=0,top=0,stck[maxn]; bool vis[maxn]; int bl[maxn]; vector<int>G[maxn]; void add(int u,int v){G[u].pb(v);} void clear(int n){ timee=scc_cnt=top=0; rep(i,1,n) { vis[i]=dfn[i]=low[i]=0; G[i].clear(); } } void tarjan(int now){ dfn[now]=low[now]=++timee; stck[++top]=now;vis[now]=1; for(auto v:G[now]){ if(!dfn[v]) tarjan(v),low[now]=min(low[now],low[v]); else if(vis[v]) low[now]=min(low[now],dfn[v]); } if(dfn[now]==low[now]){ scc_cnt++;int tmp; do{ tmp=stck[top--]; vis[tmp]=0; bl[tmp]=scc_cnt; }while(now!=tmp); } } }tar; int n,m; struct edge{int u,v,w,f;}Edge[maxm]; vector<P>G[maxn]; ll dp[maxn]; ll dfs(int now){ if(dp[now]) return dp[now]; for(auto v:G[now]){ dp[now]=max(dp[now],dfs(v.first)+v.second); } return dp[now]; } void solve(){ cin>>n>>m; rep(i,1,m){ int u,v,w,f; scanf("%d %d %d %d",&u,&v,&w,&f); Edge[i]=(edge){u,v,w,f}; D1.add(u,v,w);D2.add(v,u,w); } D1.Dijk(1,n);D2.Dijk(n,n); ll dis=D1.dis[n]; int cnt=0; rep(i,1,m){//得到最短路图 int u=Edge[i].u,v=Edge[i].v,w=Edge[i].w; if(D1.dis[u]+w+D2.dis[v]==dis){ Edge[++cnt]=Edge[i]; tar.add(Edge[i].u,Edge[i].v); } } rep(i,1,n) if(!tar.dfn[i]) tar.tarjan(i); rep(i,1,cnt){ int u=Edge[i].u,v=Edge[i].v; if(tar.bl[u]!=tar.bl[v]){ G[tar.bl[u]].pb(P(tar.bl[v],Edge[i].f)); } } ll ans=0; rep(i,1,tar.scc_cnt){ if(!dp[i]) dfs(i); ans=max(ans,dp[i]); } rep(i,1,tar.scc_cnt) dp[i]=0; printf("%lld %lld\n",dis,ans); //clear D1.clear(n);D2.clear(n);tar.clear(n); rep(i,1,n) G[i].clear(); }
03
05
这篇关于2022HDU多校第四场的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign服务间调用学习入门
- 2024-12-27OpenFeign学习入门:轻松掌握微服务通信
- 2024-12-27OpenFeign学习入门:轻松掌握微服务间的HTTP请求
- 2024-12-27JDK17新特性学习入门:简洁教程带你轻松上手
- 2024-12-27JMeter传递token学习入门教程
- 2024-12-27JMeter压测学习入门指南
- 2024-12-27JWT单点登录学习入门指南
- 2024-12-27JWT单点登录原理学习入门
- 2024-12-27JWT单点登录原理学习入门