zoukankan      html  css  js  c++  java
  • 2018.8.6 Noip2018模拟测试赛(十九)

    日期:

    八月六号

     总分:

    300分

     难度:

    提高 ~ 省选  

     得分:

    10分(MMP)

    题目目录:

      T1:Tree

      T2:异或运算

      T3:Tree Restoring

    赛后反思:

    Emmmmmmm……

    一直在打第一题…… 结果考完才发现dp少了一种情况……

    除此之外,我无话可说…… Emmmmmm……

    题解:

    T1:Tree

    树形背包dp,设$f[i][j][k(0/1/2)]$为$i$的子树中,选$j$条边,0:从$i$出发,到$i$结束/1:从$i$出发,到$i$的某个后代结束/2:后代开始,经过$i$,后代结束:

    状态转移:

    1 f[x][j+k+1][0]=min(f[x][j+k+1][0],f[x][j][0]+f[y][k][0]+2*e[i].dis);
    2 f[x][j+k+1][1]=min(f[x][j+k+1][1],f[x][j][0]+f[y][k][1]+e[i].dis);
    3 f[x][j+k+1][1]=min(f[x][j+k+1][1],f[x][j][1]+f[y][k][0]+2*e[i].dis);
    4 f[x][j+k+1][2]=min(f[x][j+k+1][2],f[x][j][1]+f[y][k][1]+e[i].dis);
    5 f[x][j+k+1][2]=min(f[x][j+k+1][2],f[x][j][0]+f[y][k][2]+2*e[i].dis);
    6 f[x][j+k+1][2]=min(f[x][j+k+1][2],f[x][j][2]+f[y][k][0]+2*e[i].dis);

    这样就能树形dp,时间复杂度 $O(n^2)$

    COMPLETE CODE:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 using namespace std;
     5 
     6 int n,k,x,y,z,tot=0,h[3005],siz[3005];
     7 long long f[3005][3005][3],ans=1e18;
     8 struct Edge{
     9     int x,y,dis,next;
    10 }e[6005];
    11 bool vis[3005];
    12 
    13 inline void add_edge(int x,int y,int z){
    14     e[++tot].x=y,e[tot].dis=z;
    15     e[tot].next=h[x],h[x]=tot;
    16 }
    17 
    18 void dfs(int x,int fa){
    19     siz[x]=1;
    20     f[x][0][0]=0;    
    21     f[x][0][1]=0;
    22     for(int i=h[x];i;i=e[i].next){
    23         if(e[i].x==fa)continue;
    24         dfs(e[i].x,x);
    25         int y=e[i].x;
    26         for(int j=siz[x]-1;j>=0;j--)
    27         for(int k=siz[y]-1;k>=0;k--){
    28             f[x][j+k+1][0]=min(f[x][j+k+1][0],f[x][j][0]+f[y][k][0]+2*e[i].dis);
    29             f[x][j+k+1][1]=min(f[x][j+k+1][1],f[x][j][0]+f[y][k][1]+e[i].dis);
    30             f[x][j+k+1][1]=min(f[x][j+k+1][1],f[x][j][1]+f[y][k][0]+2*e[i].dis);
    31             f[x][j+k+1][2]=min(f[x][j+k+1][2],f[x][j][1]+f[y][k][1]+e[i].dis);
    32             f[x][j+k+1][2]=min(f[x][j+k+1][2],f[x][j][0]+f[y][k][2]+2*e[i].dis);
    33             f[x][j+k+1][2]=min(f[x][j+k+1][2],f[x][j][2]+f[y][k][0]+2*e[i].dis);
    34         }
    35         siz[x]+=siz[e[i].x];
    36     }
    37 }
    38 
    39 int main(){
    40     memset(f,0x7f,sizeof(f));
    41     scanf("%d%d",&n,&k);
    42     for(int i=1;i<n;i++){
    43         scanf("%d%d%d",&x,&y,&z);
    44         add_edge(x,y,z);
    45         add_edge(y,x,z);
    46     }
    47     dfs(1,-1);
    48     for(int i=1;i<=n;i++)
    49         ans=min(ans,min(f[i][k-1][1],f[i][k-1][2]));
    50     printf("%lld",ans);
    51 }

    T2:异或运算

    可持久化Trie树,我之前还不知道可持久化,现在才知道,这跟主席树是一样的,是通过差分,维护区间。

    我们按位贪心,由于$n$很小,对于每一位枚举$a$序列,统计现在的位置往优了走会有多少个值,如果大于$k$,可以走,如果小于$k$,所有反着走。

    问题就这么迎刃而解了。(貌似这题用动态开点的主席树维护值域也能做……)

    CODE:

     1 #include<iostream>
     2 #include<cstdio>
     3 using namespace std;
     4 
     5 int n,m,q,x,y,l,r,k,cnt=0,tot=0;
     6 int a[1005],b[300005],root[300005];
     7 struct Trie{
     8     int siz,next[2];
     9 }v[20000005];
    10 struct Node{
    11     int l,r,val;
    12 }s[300005];
    13 
    14 void insert(int &o,int last,int x){
    15     o=++tot;
    16     int p=o,q=last;
    17     for(int i=31;i>=0;i--){
    18         v[p]=v[q],v[p].siz++;
    19         v[p].next[(x>>i)&1]=++tot;
    20         p=v[p].next[(x>>i)&1];
    21         q=v[q].next[(x>>i)&1];
    22     }
    23     v[p].siz++;
    24 }
    25 
    26 int find(int cnt,int k){
    27     int ans=0;
    28     for(int i=31;i>=0;i--){
    29         int sum=0;
    30         for(int j=1;j<=cnt;j++){
    31             bool c=(s[j].val>>i)&1;
    32             sum+=v[v[s[j].r].next[c^1]].siz
    33                 -v[v[s[j].l].next[c^1]].siz;
    34         }
    35         if(sum>=k){
    36             ans=ans<<1|1;
    37             for(int j=1;j<=cnt;j++){
    38                 bool c=(s[j].val>>i)&1;
    39                 s[j].r=v[s[j].r].next[c^1];
    40                 s[j].l=v[s[j].l].next[c^1];
    41             }
    42         }else{
    43             k-=sum,ans=ans<<1;
    44             for(int j=1;j<=cnt;j++){
    45                 bool c=(s[j].val>>i)&1;
    46                 s[j].r=v[s[j].r].next[c];
    47                 s[j].l=v[s[j].l].next[c];
    48             }
    49         }
    50     }
    51     return ans;
    52 }
    53 
    54 int main(){
    55     scanf("%d%d",&n,&m);
    56     for(int i=1;i<=n;i++)scanf("%d",a+i);
    57     for(int i=1;i<=m;i++)scanf("%d",b+i);
    58     for(int i=1;i<=m;i++)
    59         insert(root[i],root[i-1],b[i]);
    60     scanf("%d",&q);
    61     for(int i=1;i<=q;i++){
    62         scanf("%d%d%d%d%d",&x,&y,&l,&r,&k);
    63         cnt=0;
    64         for(int j=x;j<=y;j++)
    65             s[++cnt]=(Node){root[l-1],root[r],a[j]};
    66         printf("%d
    ",find(cnt,k));
    67     }
    68 }

    T3:Tree Restoring

    很容易发现离所有点最远的点定是树的直径的两个端点。(我怎么就没想到呢?)

    所有点的距离只能在$leftlceil{dover 2} ight ceil$到$d$之间,同时直径上的点两两对称,判断这些即可。

    CODE:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<algorithm>
     4 using namespace std;
     5 
     6 int n,x,a,b,t[105];
     7 
     8 int main(){
     9     scanf("%d",&n);
    10     for(int i=1;i<=n;i++){
    11         scanf("%d",&x);
    12         t[x]++,a=max(a,x);
    13     }
    14     b=a+1>>1;
    15     for(int i=b+1;i<=a;i++)
    16         if(t[i]<2){
    17             printf("Impossible");
    18             return 0;
    19         }
    20     if(a&1){
    21         if(t[b]<2){
    22             printf("Impossible");
    23             return 0;
    24         }t[b]-=2;
    25     }else{
    26         if(t[b]<1){
    27             printf("Impossible");
    28             return 0;
    29         }t[b]-=1;
    30     }
    31     for(int i=1;i<=b;i++)
    32         if(t[i]){
    33             printf("Impossible");
    34             return 0;
    35         }
    36     printf("Possible");
    37 }
  • 相关阅读:
    vue开发chrome扩展,数据通过storage对象获取
    Vue手动集成less预编译器
    Google Translate寻找之旅
    Javascript Range对象的学习
    Javascript Promises学习
    SublimeText 建立构建Node js系统
    We're sorry but demo3 doesn't work properly without JavaScript enabled. Please enable it to continue.
    npm安装包出现UNMET DEPENDENCY报错
    (转载)命令行说明中格式 尖括号 中括号的含义
    Linux重启网卡服务Failed to start LSB: Bring up/down networking.
  • 原文地址:https://www.cnblogs.com/ezoiLZH/p/9431956.html
Copyright © 2011-2022 走看看