• 2019牛客多校第七场


    A.String

    传送:https://ac.nowcoder.com/acm/contest/887/A

    题意:给定一个$0,1$字符串,要求用划分最少的部分,使得每一部分的字典序为循环的字典序最小。

    数据范围:$1<=T<=300,1<=len<=200$。

    分析:暴力拆分为以0开始以1结束的字符串,两两合并,直至不可合并。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int maxn=300;
     4 string aa[maxn],bb[maxn];
     5 char s[maxn];
     6 int tot,tot2;
     7 void init(){
     8     int len=strlen(s+1);
     9     string ss="";
    10     int flag=1; tot=0;
    11     for (int i=1;i<=len;i++){
    12         if(s[i]=='1') ss+=s[i],flag=0;
    13         else if(s[i]=='0'){
    14             if(flag) ss+=s[i];
    15             else{
    16                 aa[++tot]=ss; ss=s[i]; flag=1;
    17             }
    18         }
    19         if(i==len) aa[++tot]=ss;
    20     }
    21 }
    22 bool check(){
    23     for (int i=1;i<tot;i++){
    24         string x=aa[i],y=aa[i+1];
    25         if(x+y<=y+x) return true;
    26     }
    27     return false;
    28 }
    29 string st[maxn];
    30 void solve(){
    31     int top=1; st[1]="";
    32     for (int i=1;i<=tot;i++){
    33         string a=st[top];
    34         string b=aa[i];
    35         string tmp1=a+b,tmp2=b+a;
    36         if(tmp1<=tmp2) st[top]=tmp1;
    37         else st[++top]=b;
    38     } 
    39     tot=0;
    40     for (int i=1;i<=top;i++) aa[++tot]=st[i]; 
    41 }
    42 int main(){
    43     int t;scanf("%d",&t);
    44     while (t--){
    45         scanf("%s",s+1);
    46         init();
    47         while (1){
    48             if (check()) solve();
    49             else break;
    50         }
    51         for (int i=1;i<=tot;i++)
    52             if (i==1) cout << aa[i];
    53             else cout << " " << aa[i];
    54         cout << endl;
    55     }
    56     return 0;
    57 }
    A

    B.Irreducible Polynomial

    传送:https://ac.nowcoder.com/acm/contest/887/B

    题意:给定一个多项式,问是否可约。

    数据范围:$1<=T<=100,1<=n<=20,-10^9<=a_i<=10^9$。

    分析:实数域不可拆分多项式只有两种:一次多项式和二次的($b^2<4ac$)。

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 using namespace std;
     4 ll a[100];
     5 int main()
     6 {
     7     int t;scanf("%d",&t);
     8     while (t--)
     9     {
    10         int n;scanf("%d",&n);
    11         for (int i=n;i>=0;i--) scanf("%lld",&a[i]);
    12         if(n==0 || n==1) {printf("Yes
    ");continue;}
    13         if(n>=3) {printf("No
    ");continue;}
    14         ll dd=a[1]*a[1]-4*a[0]*a[2];
    15         if(dd<0) printf("Yes
    ");
    16         else printf("No
    ");
    17     }
    18     return 0;
    19 }
    B

    C.Governing sand

    传送:https://ac.nowcoder.com/acm/contest/887/C

    题意:有$n$种树,每种树有高度$h_i$,砍掉的花费$c_i$,数量$p_i$。要求最高的树的数量必须>=一半,问最小的砍掉其他树的花费为多少。

    数据范围:$1<=T<=30,1<=n<=10^5,1<=h_i,p_i<=10^9,1<=c_i<=200$。

    分析:从从低到高枚举最高的树,在剩下的树当中砍掉代价最小的。用权值线段树维护。

    线段树按照代价从小到大构建,然后查询代价尽可能小的。

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 #include<iostream>
     5 #define m(a,b) memset(a,b,sizeof a)
     6 #define en '
    '
     7 using namespace std;
     8 typedef long long ll;
     9 const int N=2e5+5;
    10 const ll INF=1ll<<61ll;
    11 struct node{int id;ll h;}a[N];
    12 int cmp(node x,node y){return x.h<y.h;}
    13 ll c[N],num[N],sum[N],sb[N];int r[N];
    14 ll tag[N<<2],tsum[N<<2];
    15 void build(ll l,ll r,ll pos){
    16     tag[pos]=tsum[pos]=0;
    17     if(l==r) return;
    18     ll mid=(l+r)>>1;
    19     build(l,mid,pos<<1);
    20     build(mid+1,r,pos<<1|1);
    21 }
    22 void update(ll dex,ll num,ll l,ll r,ll pos)
    23 {
    24     if(l==r) {
    25         tag[pos]+=num,tsum[pos]+=num*l;
    26         return;
    27     }
    28     ll mid=(l+r)>>1;
    29     if(dex<=mid) update(dex,num,l,mid,pos<<1);
    30     else update(dex,num,mid+1,r,pos<<1|1);
    31     tag[pos]=tag[pos<<1]+tag[pos<<1|1];//左边的数量
    32     tsum[pos]=tsum[pos<<1]+tsum[pos<<1|1];//左边的金钱
    33 }
    34 ll query(ll cnt,ll l,ll r,ll pos)//找到cnt个的最小花费
    35 {
    36     if(l==r) return l*cnt;
    37     ll mid=(l+r)>>1;
    38     if(tag[pos<<1]>=cnt) return query(cnt,l,mid,pos<<1);//左边的数量够
    39     else return tsum[pos<<1]+query(cnt-tag[pos<<1],mid+1,r,pos<<1|1);//左边的金钱+右边询问
    40 }
    41 int main(){
    42     int n;
    43     while(~scanf("%d",&n))
    44     {
    45         ll _A=0,Max=0;
    46         for(int i=1;i<=n;++i)
    47             scanf("%lld%lld%lld",&a[i].h,&c[i],&num[i]),a[i].id=i,_A+=num[i],Max=max(Max,c[i]);
    48         build(1,Max,1);
    49         sort(a+1,a+n+1,cmp); a[n+1].h=0;
    50         for (int i=n;i>=1;i--)
    51         {
    52             if (a[i].h==a[i+1].h) r[i]=r[i+1];
    53             else r[i]=i;
    54         }
    55         ll res=0,res2=0;
    56         for(int i=n;i>=1;--i)
    57         {
    58             sum[i]=res,res+=c[a[i].id]*num[a[i].id];
    59             sb[i]=res2,res2+=num[a[i].id];
    60         }
    61         res=INF;
    62         for(int i=1;i<=n;++i)
    63         {
    64             int kk=r[i];ll ttt=0;
    65             if (r[i]!=r[i+1]) ttt=num[a[i].id];
    66             else{
    67                 int j=i;
    68                 while (r[j]==r[j+1] && j<=n) ttt+=num[a[j++].id];
    69                 if (j<=n) ttt+=num[a[j].id];
    70             }
    71             ll cnt=_A-sb[kk]-ttt*2+1;
    72             ll tmp=sum[kk];
    73             if(cnt>0&&r[i]!=r[i-1]) {
    74                 tmp+=query(cnt,1,Max,1); //删除cnt个的最小花费
    75                 res=min(res,tmp);
    76             }
    77             if(cnt<=0 && r[i]!=r[i-1])res=min(res,tmp);
    78             update(c[a[i].id],num[a[i].id],1,Max,1);//在这个花费处添加num个.
    79         }
    80         printf("%lld
    ",res);
    81     }
    82     return 0;
    83 }
    C

    D.Number

    传送:https://ac.nowcoder.com/acm/contest/887/D

    题意:要求输出一个$n$位的是质数$p$的倍数的树,不存在输出T_T。

    数据范围:$1<=n<=10^6,2<=p<=10^6$。

    分析:直接构造。输出一个$p$,剩下的输出0。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3  
     4 int main()
     5 {
     6     int n,p;scanf("%d%d",&n,&p);
     7     int tmp=0,x=p;
     8     while (x) {x/=10;tmp++;}
     9     if(n<tmp) printf("T_T
    ");
    10     else
    11     {
    12         printf("%d",p);
    13         for (int i=1;i<=n-tmp;i++) printf("0");
    14         printf("
    ");
    15     }
    16     return 0;
    17 }
    D

    E.Find the median

    题解传送:https://www.cnblogs.com/changer-qyz/p/11327322.html

    J.A+B problem

    传送:https://ac.nowcoder.com/acm/contest/887/J

    题意:定义$f(x)$为$x$反转后的数。求解$f(f(a)+f(b))$。

    分析:暴力。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long ll;
     4 char a[50],b[50];
     5 int ans[50];
     6 int main(){
     7     int t;scanf("%d",&t);
     8     while (t--){
     9         scanf("%s%s",a,b);
    10         int lena=strlen(a),lenb=strlen(b);
    11         ll f=1ll; ll aa=0,bb=0;
    12         for (int i=0;i<lena;i++){
    13             aa=aa+f*(a[i]-'0');
    14             f*=10;
    15         } 
    16         f=1ll;
    17         for (int i=0;i<lenb;i++){
    18             bb=bb+f*(b[i]-'0');
    19             f*=10;
    20         }
    21         ll kk=aa+bb; int tot=0;
    22         while (kk){
    23             ans[++tot]=kk%10;
    24             kk/=10;
    25         }
    26         int i=1;
    27         while (ans[i]==0) i++;
    28         for (i;i<=tot;i++) printf("%d",ans[i]);
    29         printf("
    ");
    30     } 
    31     return 0;
    32 } 
    J

     

  • 相关阅读:
    bzoj_auto_submiter(辣鸡Py毁我青春系列)
    听说“辣鸡小隔膜”出V1.3了?
    shell脚本:统计分析 /home/ 目录用户磁盘使用情况
    shell脚本:DNS自检脚本
    Linux命令集锦:ssh命令
    Linux用户权限
    Linux文件属性
    Linux命令集锦:chown命令
    Linux命令集锦:chmod命令
    Linux命令集锦:tmux命令
  • 原文地址:https://www.cnblogs.com/changer-qyz/p/11324745.html
Copyright © 2020-2023  润新知