• 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
  • 相关阅读:
    动态规划——Best Time to Buy and Sell Stock IV
    动态规划——Split Array Largest Sum
    动态规划——Burst Ballons
    动态规划——Best Time to Buy and Sell Stock III
    动态规划——Edit Distance
    动态规划——Longest Valid Parentheses
    动态规划——Valid Permutations for DI Sequence
    构建之法阅读笔记05
    构建之法阅读笔记04
    构建之法阅读笔记03
  • 原文地址:https://www.cnblogs.com/lazytear/p/7510505.html
Copyright © 2020-2023  润新知