• 2020 省选模拟测试 Round #11 solution (20/02/15)


    【比赛链接】http://59.61.75.5:8018/contest/221

    A. 怪兽

    【题解】

    首先显然有回合越少越优. 二分求出最少需要的回合.

    分类讨论:

    ①先杀 A 后杀 B:

    二分杀 A 需要的回合,若剩下的杀不了 B 则将 A 中多余的一回合删去. 可以证明,A 中一定可以删去一回合使得刚好杀掉 A.

    ②先杀 B 后杀 A:

    最优显然构造 AAABBBAAA 的情况.

    逐位贪心,考虑后面能否杀完即可. 优先选 A. 具体细节参见代码.

    【代码】

     1 #include<bits/stdc++.h>
     2 inline int read ( void )
     3 {
     4     int x=0;char ch;
     5     while ( !isdigit(ch=getchar()) ) ;
     6     for ( x=ch^48;isdigit(ch=getchar()); ) x=(x<<1)+(x<<3)+(ch^48);
     7     return x;
     8 }
     9 const int maxn=100000+10;
    10 long long sum[maxn];
    11 char ans[3][maxn];
    12 inline void Print ( int k,int T,long long res )
    13 {
    14     printf("%lld ",res);
    15     for ( int i=1;i<=T;i++ ) putchar(ans[k][i]);
    16     puts("");
    17 }
    18 signed main()
    19 {
    20     for ( int i=1;i<=100003;i++ ) sum[i]=sum[i-1]+i;
    21     for ( int Cases=read();Cases--; )
    22     {
    23         long long ha=read(),hb=read(),atka=read(),atkb=read();
    24         long long T=std::lower_bound(sum+1,sum+100004,ha+hb)-sum;
    25         
    26         long long A=std::lower_bound(sum+1,sum+100004,ha)-sum;
    27         long long vala=A*atka+T*atkb;
    28         for ( long long i=1;i<=A;i++ ) ans[1][i]='A';
    29         for ( long long i=A+1;i<=T;i++ ) ans[1][i]='B';
    30         if ( sum[T]-sum[A]<hb ) ans[1][sum[A]-ha]='B';
    31         
    32         long long B=std::lower_bound(sum+1,sum+100004,hb)-sum;
    33         long long p=std::upper_bound(sum+1,sum+100004,sum[B]-hb)-sum-1;
    34         long long valb=T*atka+B*atkb;
    35         for ( long long i=1;i<=p;i++ ) ans[2][i]='A';
    36         for ( long long i=p+1;i<=B;i++ ) ans[2][i]='B';
    37         for ( long long i=B+1;i<=T;i++ ) ans[2][i]='A';
    38         if ( sum[T]-sum[B]+sum[p]<ha )
    39         {
    40             long long res=ha-sum[T]+sum[B];
    41             for ( long long i=1;i<=B;i++ )
    42                 if ( res>2*i or res==i ) res-=i,ans[2][i]='A';
    43                 else ans[2][i]='B';
    44         }
    45         
    46         if ( vala<valb ) Print(1,T,vala);
    47         else if ( vala>valb ) Print(2,T,valb);
    48         else
    49         {
    50             int f=1;
    51             for ( int i=1;i<=T;i++ )
    52                 if ( ans[1][i]<ans[2][i] ) break;
    53                 else if ( ans[1][i]>ans[2][i] ) { f=2;break; }
    54             Print(f,T,vala);
    55         }
    56     }
    57     return 0;
    58 }
    DTOJ4722

    B. 区间

    【题解】

    考虑转化为字符串求解. 考虑本质不同的子串,建出 SAM,则每个节点的 $right$ 大小即为这个节点的贡献.

    用单调栈维护编号,extend 时二分查找 $right$ 大小对应的编号位置,计算即可.

    【代码】

     1 #include<bits/stdc++.h>
     2 inline int read ( void )
     3 {
     4     int x=0;char ch;
     5     while ( !isdigit(ch=getchar()) ) ;
     6     for ( x=ch^48;isdigit(ch=getchar()); ) x=(x<<1)+(x<<3)+(ch^48);
     7     return x;
     8 }
     9 const int maxn=400000+10;
    10 int size=1,root=1,last=1,val[maxn],len[maxn],fa[maxn],st[maxn],a[maxn],tp;
    11 std::unordered_map<int,int> ch[maxn];long long sum[maxn],ans;
    12 inline void extend ( int c )
    13 {
    14     int np=++size,p=last;val[np]=1;len[np]=len[p]+1;last=np;
    15     while ( p and !ch[p].count(c) ) ch[p][c]=np,p=fa[p];
    16     if ( !p ) fa[np]=root;
    17     else
    18     {
    19         int q=ch[p][c];
    20         if ( len[q]==len[p]+1 ) fa[np]=q;
    21         else
    22         {
    23             int nq=++size;len[nq]=len[p]+1;fa[nq]=fa[q];
    24             fa[q]=fa[np]=nq;ch[nq]=ch[q];
    25             while ( p and ch[p][c]==q ) ch[p][c]=nq,p=fa[p];
    26         }
    27     }
    28     int L=len[np]-len[fa[np]];
    29     int pos=std::lower_bound(st+1,st+tp+1,L)-st;
    30     ans+=sum[pos-1]+1LL*a[st[pos]]*(L-st[pos-1]);
    31 }
    32 inline void C ( void )
    33 {
    34     for ( int i=1;i<=size;i++ ) ch[i].clear(),fa[i]=0;
    35     root=last=size=1;tp=0;ans=0;
    36 }
    37 signed main()
    38 {
    39     for ( int T=read();T--;C() )
    40     {
    41         int n=read();
    42         for ( int i=1;i<=n;i++ )
    43         {
    44             a[i]=read();
    45             while ( tp and a[st[tp]]<=a[i] ) tp--;
    46             st[++tp]=i;sum[tp]=sum[tp-1]+1LL*a[i]*(st[tp]-st[tp-1]);
    47             extend(a[i]);
    48         }
    49         printf("%lld
    ",ans);
    50     }
    51     return 0;
    52 }
    DTOJ4720
  • 相关阅读:
    很简单的字节转换函数
    PHP获取用户操作系统信息
    PHP调用COM获得服务器硬件信息
    杂碎记录
    Math类使用记录
    hbase命令使用记录
    shell脚本学习
    多个job存依赖关系如何使用
    hbase的API并且使用多个rowkey分段直接读取数据
    shell学习记录
  • 原文地址:https://www.cnblogs.com/RenSheYu/p/12313604.html
Copyright © 2020-2023  润新知