杂题整理 简单复习
随心情更新 不复习就是模拟赛遇到三月份写的欧拉路 想一年都不会
二分 POJ3104
题意:有一些衣服,每件衣服有一定水量,有一个烘干机,每次可以烘一件衣服,每分钟可以烘掉k滴水。
每件衣服没分钟可以自动蒸发掉一滴水,用烘干机烘衣服时不蒸发。问最少需要多少时间能烘干所有的衣服。、
其实和模拟赛T2 很像 你面临着两个决策的选择 不过一个需要等待 一个可以直接进行
考虑 此时二分这个风干的时间 mid
那么 考虑check怎么写 如果一个点的晾干时间 > 此时二分的mid 那么我们考虑 最有策略一定是烘干一段时间 然后晾干一段时间
那么我们完全可以计算出来 这个烘干时间 (num[i] - mid) / (k - 1) 考虑此时能不能做完这个事情即可
#include<bits/stdc++.h> using namespace std; const int N=100100; typedef long long ll; template<typename T>inline void read(T &x) { x=0;T f=1,ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x*=f; } ll n,k,a[N]; inline bool check(ll mid) { ll res=0; if(k==1) return 1; for(int i=1;i<=n;i++) { if(a[i]>mid) res+=(a[i]-mid+k-2)/(k-1); } return mid<res; } int main() { read(n); ll sum=0; for(int i=1;i<=n;i++) { read(a[i]); sum=max(sum,a[i]); } read(k); ll l=0,r=sum; while(l+1<r) { int mid=(l+r)>>1; if(check(mid)) l=mid; else r=mid; } printf("%lld\n",r); return 0; }
树上博弈 LOJ#10243. 「一本通 6.7 例 3」移棋子游戏
给定一个有向无环图 上面有若干个棋子 每个人每次能沿着一条边移动一次 问你先手 或者 后手 谁赢
我们主要到 有多个棋子的时候 我们是多个有向图游戏 根据博弈论的知识 我们知道 多个有向图游戏的和 就是 每一个有向图 游戏的和异或起来
考虑 此时我们对于一个点x 我们知道 所有后继状态 那么我们可以知道当前这个点的状态 那么考虑 我们暴力求出来每个点的sg值即可
那么怎么做呢 我们可以反向建图 进行拓扑 同时 更新每一个儿子 当然你可以 dfs 回溯的时候 求出每个点 是P态还是N态
以为 一个节点 所有后继都是必胜态 那么此时 这个点就是必败态 只要有一个必败态 当前点就是必胜态
可以理解 一下 我们的mex 运算原则
#include<bits/stdc++.h> using namespace std; template<typename T>inline void read(T &x) { x=0;T f=1,ch=getchar(); while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();} x*=f; } const int N=5100; struct gg { int y,next,v; }a[N<<1],e[N<<1]; int n,m,x,k,y,tmp,tot,vis[N],sg[N],lin[N],linc[N],du[N]; queue<int>q; inline void add(int x,int y) { a[++tot].y=y; a[tot].next=lin[x]; lin[x]=tot; e[tot].y=x; e[tot].next=linc[y]; linc[y]=tot; } int main() { // freopen("bigraph.in","r",stdin); // freopen("bigraph.out","w",stdout); read(n); read(m); read(k); for(int i=1;i<=m;++i) { read(x); read(y); add(x,y);++du[x]; } for(int i=1;i<=n;++i) if(!du[i]) q.push(i); while(!q.empty()) { int x=q.front();q.pop();tmp=0; for(int i=lin[x];i;i=a[i].next) { int y=a[i].y; vis[sg[y]]=1,tmp=max(tmp,sg[y]); } for(int i=0;i<=tmp+1;++i)if(!vis[i]){sg[x]=i;break;} for(int i=0;i<=tmp;++i) vis[i]=0; for(int i=linc[x];i;i=e[i].next) { int y=e[i].y; --du[y]; if(!du[y]) q.push(y); } } int ans=0; for(int i=1;i<=k;i++) { read(x); ans^=sg[x]; } printf("%s\n",ans?"win":"lose"); return 0; }