• 2022“杭电杯”中国大学生算法设计超级联赛(5)


    Bragging Dice

     两个人掷骰子,两人都知道对方手中和自己手中的牌数,现在有两种操作,一种是挑战,即打开盖子,看是否是前一人说的那样;另一种是声称,即给出判断,类似有x个y点的骰子这样的说法。给出两人手中的牌,判断谁会赢。

    思路:很坑人的签到题。因为声称是有要求的每次要么x大于上一个x,y是任意的;要么x等于前一个x,y大于上一个y。这样其实先手有策略控制claim的次数,即先手最大化x和y,这样使得后手无法接着claim,先手必赢。

    AC Code:

    1. #include
    2. typedef long long ll;
    3. const int N=15;
    4. int t,n,x;
    5. int a[N],b[N];
    6. int main(){
    7. std::ios::sync_with_stdio(false);
    8. std::cin.tie(0);
    9. std::cout.tie(0);
    10. std::cin>>t;
    11. while(t--){
    12. std::cin>>n;
    13. memset(a,0,sizeof(a));
    14. memset(b,0,sizeof(b));
    15. for(int i=1;i<=n;i++){
    16. std::cin>>x;
    17. a[x]++;
    18. }
    19. for(int i=1;i<=n;i++){
    20. std::cin>>x;
    21. b[x]++;
    22. }
    23. bool flag=false;
    24. for(int i=1;i<=6;i++){
    25. if(a[i]>1||b[i]>1){
    26. flag=true;
    27. break;
    28. }
    29. }
    30. std::cout<<(flag?"Win!":"Just a game of chance.")<<'\n';
    31. }
    32. return 0;
    33. }

    Buy Figurines

     有n个人买东西,给出n个人来的时间和需要的时间,一共有m个窗口,每个人会优先选择编号最小且人最少的窗口,问从第一个人来到最后一个人走需要多长时间。

    思路:比较麻烦的模拟题。我们不仅要维护每一个队列,还要对每个人的开始时间结束时间和在哪买全都包括。如果简单的用m个队列的话会T,这里有种线段树维护的方式,线段树维护的是最适合把人放在哪个位置,用优先队列维护每个人的信息,细节见代码。

     AC Code:

    1. #include
    2. #define int long long
    3. typedef std::pair<int,int>PII;
    4. const int N=2e5+5;
    5. int t,n,m;
    6. int leave[N];
    7. struct SegmentTree{
    8. struct Tree{
    9. int l,r;
    10. int pos,min;
    11. }tr[N<<2];
    12. struct node{
    13. int sta,len;
    14. bool operator <(const node &a) const{
    15. return sta
    16. }
    17. }e[N];
    18. void pushup(int u){
    19. tr[u].min=std::min(tr[u<<1].min,tr[u<<1|1].min);
    20. if(tr[u<<1].min==tr[u].min) tr[u].pos=tr[u<<1].pos;
    21. else tr[u].pos=tr[u<<1|1].pos;
    22. }
    23. void build(int u,int l,int r){
    24. tr[u]={l,r,l,0};
    25. if(l==r) return;
    26. else{
    27. int mid=l+r>>1;
    28. build(u<<1,l,mid);
    29. build(u<<1|1,mid+1,r);
    30. pushup(u);
    31. }
    32. }
    33. void modify(int u,int x,int v){
    34. if(x==tr[u].l&&x==tr[u].r) tr[u].min+=v;
    35. else{
    36. int mid=tr[u].l+tr[u].r>>1;
    37. if(x<=mid) modify(u<<1,x,v);
    38. if(x>mid) modify(u<<1|1,x,v);
    39. pushup(u);
    40. }
    41. }
    42. }ST;
    43. signed main(){
    44. std::ios::sync_with_stdio(false);
    45. std::cin.tie(0);
    46. std::cout.tie(0);
    47. std::cin>>t;
    48. while(t--){
    49. std::cin>>n>>m;
    50. for(int i=1;i<=n;i++){
    51. int a,b;
    52. std::cin>>a>>b;
    53. ST.e[i]={a,b};
    54. }
    55. for(int i=1;i<=m;i++){
    56. leave[i]=0;
    57. }
    58. ST.build(1,1,m);
    59. std::priority_queue,std::greater>pq;
    60. std::sort(ST.e+1,ST.e+1+n);
    61. int ans=0;
    62. for(int i=1;i<=n;i++){
    63. while(!pq.empty()&&pq.top().first<=ST.e[i].sta){
    64. ST.modify(1,pq.top().second,-1);
    65. pq.pop();
    66. }
    67. int pos=ST.tr[1].pos;
    68. ST.modify(1,pos,1);
    69. leave[pos]=std::max(ST.e[i].sta,leave[pos])+ST.e[i].len;
    70. pq.push({leave[pos],pos});
    71. ans=std::max(leave[pos],ans);
    72. }
    73. std::cout<'\n';
    74. }
    75. return 0;
    76. }

     os:线段树yyds!!!

    Slipper

     给出一棵树,每一条边之间有权值,也可以花费p传送到距离k层的位置,求最短路。

    思路:主要问题是如何建图和如何解决数据范围较大的问题。如果在每一个相距k层的点之间建边,n^2肯定不可行,考虑两层之间新建一层,入度边权为0,出度为p,解决了建边问题之后直接跑Dijkstra求最短路即可。

    AC Code;

    1. #include
    2. typedef long long ll;
    3. typedef std::pairint>PII;
    4. #define INF 0x3f3f3f3f
    5. const int N=4e6+5;
    6. int t,n,k,p,S,T,cnt;
    7. int e[N<<1],next[N<<1],w[N<<1],deep[N],head[N];
    8. ll dis[N];
    9. std::vector<int>v[N];
    10. bool vis[N];
    11. void add_edge(int u,int v,int x){
    12. e[cnt]=v;
    13. w[cnt]=x;
    14. next[cnt]=head[u];
    15. head[u]=cnt++;
    16. }
    17. void DFS(int u,int fa){
    18. deep[u]=deep[fa]+1;
    19. v[deep[u]].push_back(u);
    20. for(int i=head[u];~i;i=next[i]){
    21. int j=e[i];
    22. if(j==fa) continue;
    23. DFS(j,u);
    24. }
    25. }
    26. void Dijkstra(){
    27. std::priority_queue,std::greater>pq;
    28. memset(dis,INF,sizeof(dis));
    29. memset(vis,0,sizeof(vis));
    30. dis[S]=0;
    31. pq.push({dis[S],S});
    32. while(!pq.empty()){
    33. auto tt=pq.top();
    34. pq.pop();
    35. int now=tt.second;
    36. if(vis[now]) continue;
    37. vis[now]=true;
    38. for(int i=head[now];~i;i=next[i]){
    39. int u=e[i];
    40. if(dis[u]>dis[now]+w[i]){
    41. dis[u]=dis[now]+w[i];
    42. pq.push({dis[u],u});
    43. }
    44. }
    45. }
    46. }
    47. signed main(){
    48. std::ios::sync_with_stdio(false);
    49. std::cin.tie(0);
    50. std::cout.tie(0);
    51. std::cin>>t;
    52. while(t--){
    53. memset(head,-1,sizeof(head));
    54. cnt=0;
    55. std::cin>>n;
    56. for(int i=1;i<=n;i++){
    57. v[i].clear();
    58. }
    59. for(int i=1;i
    60. int a,b,c;
    61. std::cin>>a>>b>>c;
    62. add_edge(a,b,c);
    63. add_edge(b,a,c);
    64. }
    65. std::cin>>k>>p>>S>>T;
    66. DFS(1,0);
    67. for(int i=1;i<=n;i++){
    68. for(auto u:v[i]){
    69. add_edge(u,i+n*2,0);
    70. add_edge(i+n,u,0);
    71. }
    72. if(i-k>0) add_edge(i+n*2,i-k+n,p);
    73. if(i+k<=n) add_edge(i+n*2,i+k+n,p);
    74. }
    75. Dijkstra();
    76. std::cout<'\n';
    77. }
    78. return 0;
    79. }

    os:感觉这个题和之前在kuangbin专题做的最短路难度挺相似的,,好像还有一个题和这个idea解题的差不多,只不过弱队签到都要搞好久,,

    下一个NTT啊,没学,跑路!

  • 相关阅读:
    梦开始的地方—— C语言动态内存管理(malloc+calloc+realloc+free)
    网页前端设计-作业四(HTML5)
    【学习笔记】设计算法(Design Algorithm)
    Node.js 实战 第1章 欢迎进入Node.js 的世界 1.4 Node 自带的工具 1.4.3 调试器
    TensorFlow图像多标签分类实例
    【ORACLE】谈一谈NVARCHAR2、NCHAR、NCLOB等数据类型和国家字符集
    2022 【SPDK原理最新视频讲解】
    Baklib|知识库应用场景:制作员工培训手册
    整车行业 SAP APO 开发备忘(刘欣)
    Voip测试工具
  • 原文地址:https://blog.csdn.net/m0_62289613/article/details/126643690