CS R17 C(思维DP) D(二进制,淘汰) E(好题:博弈+DP)

来源:互联网 发布:儿童dna数据库有用吗 编辑:程序博客网 时间:2024/05/21 17:09
题意:给出排列a,操作:将任意一个数放到开头或者结尾.
n<=1e5,问将序列变为从小到的顺序的最小操作次数,并输出方案.

显然每个元素只要移动一次,若同一个元素有多次移动,则用其最后一次移动 造成的效果是相同的.
每个元素要么不移动要么移动一次, 求最少需要操作元素 -> 求最多不需要操作的元素有多少个?
假如不需要移动的元素集合S 则S显然为连续的一段数,否则需要移动.

设dp[a[i]]为以a[i]结尾的最长的一段连续序列,dp[a[i]]=dp[a[i]-1]+1. a[i]-1在a[i]之后则dp[a[i]为1.

找到元素个数最多的S之后,mx=max(S),mn=min(S) 则只要把mx+1,mx+2..n移动最后,把mn-1,mn-2...1.移动到前面即可得到方案.

#include <bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int,int> ii;const int N=2e5+20,inf=0x3f3f3f3f;int n,a[N],dp[N];int main(){int res=0,l,r;scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=n;i++){dp[a[i]]=dp[a[i]-1]+1;if(res<dp[a[i]])res=dp[a[i]],r=a[i];}l=r-res+1;cout<<n-res<<endl;for(int i=l-1;i>=1;i--)printf("%d 0\n",i);for(int i=r+1;i<=n;i++)printf("%d 1\n",i);return 0;}

Problem D
题意:给出n个数,问选k个数,and运算最大能为多少?
n,k<=1e5,a[i]<=1e9.

高位能为1尽量为1,bit位从高到低,采用淘汰法.
若bit位为1的>=k个 则这些数为待选  其余的数肯定不能选 淘汰掉即可.
若待选元素中bit位为1的<k个,则该位只能为0.

#include <bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int,int> ii;const int N=2e5+20,inf=0x3f3f3f3f;int n,k,a[N],vis[N];int main(){ll ans=0;cin>>n>>k;for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=31;i>=0;i--){int cnt=0;for(int j=1;j<=n;j++){if(vis[j])continue;if((a[j]>>i)&1)cnt++;}if(cnt>=k){ans+=(1ll<<i);for(int j=1;j<=n;j++){if((((a[j]>>i)&1))==0)vis[j]=1;}}}cout<<ans<<endl;return 0;}

Problem E
题意:n点m条边的有向无环图(DAG),图中总共有k点能量.
给出初始k个能量的分布位置(同一个结点上可以有多个能量)
现在A,B两人轮流操作,每轮将所有的能量移动到其能到达下一个结点(若有多个结点选择,选最优的).
n,m,k<=1e5,当某人不能操作时算输,问A先手是否必胜?


先考虑简单的情况,只有一个石子,为每个结点定义状态n/p 表示石头在这个结点开始时,先手是必败还是必胜?
所以当某个结点出去结点都为必胜时,该结点为必败.
存在出的的某个结点为必败时 该结点为必胜.


现在有多个石子.若此时所有石子为所在结点都为必胜或者必败 游戏就可以结束了
但是存在有些为必胜 有些为必败  此时应该如何解决?
Alice此时先手 对于状态为必胜的石子 Alice总是有机会移动,对于状态为必败的石子,Alice会先于BoB无法移动的.BOB对必败必胜的石子也是如此.
则最优的策略就是 Alice尽早结束它必胜的石子,也就是让BoB尽早出现无法移动的局面,然后尽量延迟必败石子的移动次数 让自己活的更久.


dp[i]为i开始移动石头的次数,对于结点i
若i为必胜态,则先手的要让它尽快结束,移动到dp[v]最小的一个必败态上.
若i为必败态,则要拖延时间 移动到dp[v]最大的一个v上即可.


总共的轮数取决于:所有初始有石头结点开始移动的次数的最小值.

#include <bits/stdc++.h>using namespace std;typedef long long ll;typedef pair<int,int> ii;const int N=2e5+20,inf=0x3f3f3f3f;int n,c[N],dp[N],ans;vector<int> e[N];int f(int u){if(dp[u]!=-1)return dp[u];int res=0;for(int i=0;i<e[u].size();i++){int v=e[u][i];f(v);if(dp[v]%2)// go v then u is p{if(res%2==0)//u is pres=max(res,dp[v]+1);}else{if(res%2==0)// u is actually nres=dp[v]+1;elseres=min(res,dp[v]+1);}}return dp[u]=res;}int main(){int n,m,k;memset(dp,-1,sizeof(dp));cin>>n>>m>>k;for(int i=1;i<=k;i++)scanf("%d",&c[i]);int u,v,ans=inf;for(int i=1;i<=m;i++){scanf("%d%d",&u,&v);e[u].push_back(v);}for(int i=1;i<=k;i++)ans=min(ans,f(c[i]));puts(ans%2?"A":"B");return 0;}






阅读全文
0 0
原创粉丝点击