2017.09.10校内训练

T1:CCT

 

题解:对于一个特征a1a2a3…am,我们可以用(a1-a1)(a2-a1)…(am-a1)来表示它。然后再做对每一位前缀和(s1-s1)(s2-s1)(s3-s1)…(sm-s1)。易发现:当两个位置i,j前缀和相同时,i+1到j或i到j-1即是一种可行的选法。用set记住每个前缀和最早出现的位置,对每个位置在set中查询并更新答案即可。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #include<set>
 7 using namespace std;
 8 int n,x,ans=0,k;
 9 struct node{
10     int num;
11     int dif[31];
12     bool operator <(const node &b)const{
13         int i;
14         for(i=1;i<k;++i){
15             if(dif[i]!=b.dif[i])  return dif[i]<b.dif[i];
16         }
17         return false;
18     }
19 }t;
20 std::set<node> s;
21 std::set<node>::iterator it;
22 int sum[100001][31];
23 int max(int a,int b){
24     return a>b?a:b;
25 }
26 int main(){
27     freopen("cct.in","r",stdin);
28     freopen("cct.out","w",stdout);
29     scanf("%d%d",&n,&k);
30     int i,j;
31     for(i=1;i<=n;++i){
32         scanf("%d",&x);
33         for(j=1;j<=k;++j){
34             sum[i][j]=sum[i-1][j];
35             if(x&(1<<(j-1))) sum[i][j]++;
36         }
37     }
38     ans=0;t.num=0;
39     for(i=1;i<k;++i){
40         t.dif[i]=0;
41     }
42     s.insert(t);
43     for(i=1;i<=n;++i){
44         t.num=i;
45         for(j=1;j<k;++j){
46             t.dif[j]=sum[i][j]-sum[i][j+1];
47         }
48         it=s.find(t);
49         if(it==s.end()) s.insert(t);
50         else ans=max(ans,i-(*it).num);
51     }
52     printf("%d\n",ans);
53     return 0;
54 }
cct.cpp

- - - - - - - - - - - - - - - - - 

T2:MHM

 

题解:二分上课的节数并check。类似题目请参考NOIP2015跳石头。注意在输入完要先排序。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<algorithm>
 5 #include<cstring>
 6 #include<cmath>
 7 using namespace std;
 8 int n,m,k,l,r,mid,ans;
 9 int a[50010],wake[50010];
10 bool check(int x){
11     int cnt=0,now=0;
12     for(int i=1;i<=m;++i){
13         if(wake[i]+now<x){
14             now+=wake[i]+1;
15             cnt++;
16         }
17         else  now=0;
18     }
19     if(cnt>k)  return false;
20     else  return true;
21 }
22 int main(){
23     freopen("mhm.in","r",stdin);
24     freopen("mhm.out","w",stdout);
25     scanf("%d%d%d",&n,&m,&k);
26     int i,j;
27     for(i=1;i<=m;++i){
28         scanf("%d",a+i);
29     }
30     a[0]=0;a[++m]=n;
31     sort(a,a+m+1);
32     for(i=1;i<=m;++i){
33         wake[i]=a[i]-a[i-1]-1;
34     }
35     l=0;r=n;
36     while(l+1<r){
37         int mid=(l+r)>>1;
38         if(check(mid))  l=mid;
39         else  r=mid-1;
40     }
41     if(check(r))  ans=r;
42     else  ans=l;
43     printf("%d\n",ans);
44     return 0;
45 }
mhm.cpp

- - - - - - - - - - - - - - - - 

T3:AAFA

 

题解:按照截至时间排序从前往后选。当选到第i个时,若已经选择的题目数量小于ti,则该时间选择它必定比不选更优。若已经选择的题目数量等于ti,则比较第i题的收益和已选择题目的最小收益,取更优者。已选择的题目用优先队列维护。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cstdlib>
 5 #include<algorithm>
 6 #include<cmath>
 7 #include<queue>
 8 #include<vector>
 9 #define ll long long
10 using namespace std;
11 struct node{
12     ll t,w;
13 }te[100010];
14 int n,ti=0;
15 ll ans=0,s;
16 bool cmp(node a,node b){
17     if(a.t==b.t)  return a.w>b.w;
18     return a.t<b.t;
19 }
20 priority_queue<int,vector<int>,greater<int> > pq;
21 int main(){
22     freopen("aafa.in","r",stdin);
23     freopen("aafa.out","w",stdout);
24     scanf("%d",&n);
25     int i,j;
26     for(i=1;i<=n;++i){
27         scanf("%lld%lld",&te[i].t,&te[i].w);
28         //ti=max(ti,te[i].t);
29     }
30     sort(te+1,te+n+1,cmp);
31     int cnt=1;
32     ans=0;
33     for(i=1;i<=n;++i){
34         s=pq.size();
35         if(s<te[i].t)  pq.push(te[i].w);
36         else{
37             if(s==te[i].t){
38                 if(pq.top()<te[i].w){
39                     pq.pop();
40                     pq.push(te[i].w);
41                 }
42             }
43         }
44     }
45     ans=0;
46     while(!pq.empty()){
47         ans+=pq.top();pq.pop();
48     }
49     printf("%lld\n",ans);
50     return 0;
51 }
aafa.cpp

- - - - - - - - - - - - - 

T4:ZZI

 

题解:在一个房子造发电机可以看作把它和已经通电的房子连边,权值为0,因此改变边权直接跑最小生成树即可。

代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 #include<algorithm>
 6 #define inf 0x7f7f7f7f
 7 using namespace std;
 8 int n,ans,minn=inf;
 9 int v[310],dist[310];
10 int a[310][310];
11 bool used[310];
12 int min(int a,int b){
13     return a<b?a:b;
14 }
15 int prim(){
16     int next,maxn,res=0;
17     int i,j;
18     for(;;){
19         next=-1;maxn=inf;
20         for(i=1;i<=n;++i){
21             if(!used[i] &&dist[i]<maxn){
22                 maxn=dist[i];next=i;
23             }
24         }
25         if(next==-1)  break ;
26         used[next]=true;
27         res+=dist[next];//dist[next]=0;
28         for(i=1;i<=n;++i){
29             if(!used[i])  dist[i]=min(dist[i],a[next][i]);
30         }
31     }
32     return res;
33 }
34 int main(){
35     freopen("zzi.in","r",stdin);
36     freopen("zzi.out","w",stdout);
37     scanf("%d",&n);
38     int i,j;
39     minn=inf;
40     for(i=1;i<=n;++i){
41         scanf("%d",dist+i);
42     }
43     for(i=1;i<=n;++i){
44         for(j=1;j<=n;++j){
45             scanf("%d",&a[i][j]);
46         }
47     }
48     printf("%d\n",prim());
49     return 0;
50 }
zzi.cpp
原文地址:https://www.cnblogs.com/lazytear/p/7510505.html