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\n");continue;}
13         if(n>=3) {printf("No\n");continue;}
14         ll dd=a[1]*a[1]-4*a[0]*a[2];
15         if(dd<0) printf("Yes\n");
16         else printf("No\n");
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 '\n'
 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\n",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\n");
10     else
11     {
12         printf("%d",p);
13         for (int i=1;i<=n-tmp;i++) printf("0");
14         printf("\n");
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("\n");
30     } 
31     return 0;
32 } 
J

 

 

posted @ 2019-08-09 00:43  Changer-qyz  阅读(243)  评论(0编辑  收藏  举报