• NOIP2015D2总结


      今天居然考了一套题。NOIP2015D2。

      这是当年的战绩:

      

      360的一等奖线。好强啊!

      之前做过2015的D1,但我确实不会做landlord……今天曾祥瑞学长和林可学姐都来了,他们说,朱昶宇AK,看见landlord时蒙了便按照自己平时的套路来打程序,看见transport时蒙了便暴力乱搞……

      我不想说,经过了不懈的努力,我才让transport成了95,而他轻轻松松暴力乱搞过了最后那个防AK点。我不想说,当时全省只有他一个人A了这道题。

      太强了!

      好的,现在我们该静一静了。

      第一题,stone,典型的二分答案例题(套贪心),但是二分策略确实很伤人头脑。

     1 #define PN "stone"
     2 #include <cstdio>
     3 int l, n, m, d[50010];
     4 int main() {
     5     freopen(PN".in","r",stdin);
     6     freopen(PN".out","w",stdout);
     7     scanf("%d%d%d",&l,&n,&m);
     8     d[0]=0;for( int i = 1; i <= n; i++ ) scanf("%d",&d[i]);d[n+1]=l;
     9     int lf=1,rg=l;
    10     while(lf<=rg) {
    11         int mid=(lf+rg)>>1, pos=0, num=0;
    12         for( int i = 1; i <= n+1; i++ ) if(d[i]-d[pos]>=mid) pos=i;else num++;
    13         if(num<=m) lf=mid+1;
    14         else rg=mid-1;//?
    15     }
    16     printf("%d
    ",rg);
    17     return 0;
    18 }
    stone

      第二题,那啥,很明显是可以套路化的,不知道难在哪里。

     1 #define PN "substring"
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 int n, m, p, f[2][210][210];
     6 char A[1010], B[210];
     7 inline int add(int a,int b) {static int MOD=1e9+7;if(a-MOD+b>0) return a-MOD+b;return a+b;}
     8 int main() {
     9     freopen(PN".in","r",stdin);
    10     freopen(PN".out","w",stdout);
    11     scanf("%d%d%d%s%s",&n,&m,&p,A,B);
    12     memset(f,0,sizeof(f));f[0][0][0]=1;
    13     for( int i = 1; i <= n; i++ ) for( int j = std::min(i,m); j >= 0; j-- ) for( int k = std::min(i,p); k >= 0; k-- ) {
    14         f[0][j][k]=add(f[1][j][k],f[0][j][k]);
    15         if(j!=0&&A[i-1]==B[j-1]) f[1][j][k]=add(add(f[1][j-1][k],f[1][j-1][k-1]),f[0][j-1][k-1]);
    16         else f[1][j][k]=0;
    17     }
    18     printf("%d
    ",add(f[0][m][p],f[1][m][p]));
    19     return 0;
    20 }
    substring

      第三题,transport,这道题理论上需要先处理处每个方案的LCA,以及这一段的距离。然后,我们就可以愉快的二分答案。找出那些超了限额的方案,看他们所共有的线路。最值减最值,与mid比较一番,就可以愉快的得出结果了。但是n,m<=300000伤不起啊。

      好的,不多说了。最后一题挂个代码吧。

     1 #define PN "transport"
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <algorithm>
     5 using namespace std;
     6 template<class T>inline void readin(T &res) {
     7     static char ch;while((ch=getchar())<'0'||ch>'9');
     8     res=ch-48;while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+ch-48;
     9 }
    10 
    11 const int N = 300000+10;
    12 const int M = 300000+10;
    13 struct EDGE {int v, upre, w;}g[N];
    14 int head[N], ne=0;
    15 inline void adde(int u,int v,int w) {g[++ne]=(EDGE){v,head[u],w},head[u]=ne;}
    16 
    17 int n, m, u, v, w, s, t;
    18 
    19 const int S = 19;
    20 int dep[N], anc[N][S+1], dis[N], edg[N], A[M], B[M], C[M], LEN[M];
    21 void DFS(int u,int fa) {
    22     anc[u][0]=fa;
    23     for( int j = 1; j <= S; j++ ) anc[u][j]=anc[anc[u][j-1]][j-1];
    24     for( int i = head[u]; i; i = g[i].upre ) {
    25         int v=g[i].v;
    26         if(v==fa) continue;
    27         edg[v]=g[i].w;dep[v]=dep[u]+1;dis[v]=dis[u]+g[i].w;DFS(v,u);
    28     }
    29 }
    30 
    31 int lca(int u,int v) {
    32     if(dep[u]<dep[v]) swap(u,v);
    33     for( int t=dep[u]-dep[v],p=0; t; t>>=1,p++ ) if(t&1) u=anc[u][p];
    34     if(u==v) return u;
    35     for( int p = S; anc[u][0]!=anc[v][0]; p-- ) if(anc[u][p]!=anc[v][p]) u=anc[u][p], v=anc[v][p];
    36     return anc[u][0];
    37 }
    38 
    39 int counter, maxl=0, flag[N], ans;
    40 void DFS1(int u,int fa) {
    41     for( int i = head[u]; i; i = g[i].upre ) {
    42         int v = g[i].v;
    43         if(v==fa) continue;
    44         DFS1(v,u);
    45         flag[u]+=flag[v];
    46     }
    47     if(flag[u]==counter) ans=max(ans,edg[u]);
    48 }
    49 bool check(int limit) {
    50     ans=0;counter=0;memset(flag,0,sizeof(flag));for( int i = 1; i <= m; i++ ) if(LEN[i]>limit) counter++, flag[A[i]]++, flag[B[i]]++, flag[C[i]]-=2;
    51     DFS1(1,1);return maxl-ans<=limit;
    52 }
    53 
    54 int main() {
    55     freopen(PN".in","r",stdin);
    56     freopen(PN".out","w",stdout);
    57     readin(n);readin(m);for( int i = 1; i < n; i++ ) {readin(u);readin(v);readin(w);adde(u,v,w);adde(v,u,w);}
    58     DFS(1,1);
    59     for( int i = 1; i <= m; i++ ) {
    60         readin(A[i]);readin(B[i]);C[i]=lca(A[i],B[i]);
    61         LEN[i]=dis[A[i]]+dis[B[i]]-dis[C[i]]*2;maxl=max(maxl,LEN[i]);
    62     }
    63     int lf=0, rg=maxl-1;
    64     while(lf<=rg) {
    65         int mid=(lf+rg)>>1;
    66         if(check(mid)) rg=mid-1;
    67         else lf=mid+1;
    68     }
    69     printf("%d
    ",rg+1);
    70     return 0;
    71 }
    transport

       后来:啊啊啊啊啊。我把最开始求LCA的ST表倍增换成了并查集tarjan,在教师老年机上又WA又T(后来经过考究,是因为u==v时tarjan的bug)。但我在BZOJ上交了一下。 

    并查集tarjan  Accepted
    36200 kb  9528 ms
    ST表倍增 Accepted 46452 kb 9700 ms

      是为什么?人品吗?

     1 /**************************************************************
     2     Problem: 4326
     3     User: Doggu
     4     Language: C++
     5     Result: Accepted
     6     Time:9528 ms
     7     Memory:36200 kb
     8 ****************************************************************/
     9  
    10 #define PN "transport"
    11 #include <cstdio>
    12 #include <cstring>
    13 #include <algorithm>
    14 using namespace std;
    15 template<class T>inline void readin(T &res) {
    16     static char ch;while((ch=getchar())<'0'||ch>'9');
    17     res=ch-48;while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+ch-48;
    18 }
    19  
    20 const int N = 300000+10;
    21 const int M = 300000+10;
    22 struct EDGE {int v, upre, w, lca;}g[N*2], r[M*2];
    23 int head[N], ne=0, read[N], re=0;
    24 inline void adde(int u,int v,int w) {g[++ne]=(EDGE){v,head[u],w},head[u]=ne;}
    25 inline void addr(int u,int v,int w) {r[++re]=(EDGE){v,read[u],w},read[u]=re;}
    26  
    27 int n, m, u, v, w, s, t;
    28  
    29 int fax[N], dis[N], edg[N], A[M], B[M], C[M], LEN[M];
    30 bool vis[N];
    31 int find(int x) {
    32     if(fax[x]==x) return x;
    33     return fax[x]=find(fax[x]);
    34 }
    35 void DFS(int u,int fa) {
    36     for( int i = head[u]; i; i = g[i].upre ) {
    37         int v=g[i].v;
    38         if(v==fa) continue;
    39         edg[v]=g[i].w;dis[v]=dis[u]+g[i].w;DFS(v,u);
    40         fax[v]=find(u);vis[v]=1;
    41     }
    42     for( int i = read[u]; i; i = r[i].upre ) if(vis[r[i].v]) r[i].lca=find(r[i].v);
    43 }
    44  
    45 int counter, maxl=0, flag[N], ans;
    46 void DFS1(int u,int fa) {
    47     for( int i = head[u]; i; i = g[i].upre ) {
    48         int v = g[i].v;
    49         if(v==fa) continue;
    50         DFS1(v,u);
    51         flag[u]+=flag[v];
    52     }
    53     if(flag[u]==counter) ans=max(ans,edg[u]);
    54 }
    55 bool check(int limit) {
    56     ans=0;counter=0;memset(flag,0,sizeof(flag));for( int i = 1; i <= m; i++ ) if(LEN[i]>limit) counter++, flag[A[i]]++, flag[B[i]]++, flag[C[i]]-=2;
    57     DFS1(1,1);return maxl-ans<=limit;
    58 }
    59  
    60 int main() {
    61     //freopen(PN".in","r",stdin);
    62     //freopen(PN".out","w",stdout);
    63     readin(n);readin(m);for( int i = 1; i < n; i++ ) {readin(u);readin(v);readin(w);adde(u,v,w);adde(v,u,w);}
    64     for( int i = 1; i <= m; i++ ) {readin(A[i]);readin(B[i]);addr(A[i],B[i],i);addr(B[i],A[i],i);}
    65     for( int i = 1; i <= n; i++ ) fax[i]=i;memset(vis,0,sizeof(vis));
    66     DFS(1,1);for( int i = 1; i <= re; i++ ) if(r[i].lca) C[r[i].w]=r[i].lca;
    67     for( int i = 1; i <= m; i++ ) LEN[i]=dis[A[i]]+dis[B[i]]-dis[C[i]]*2, maxl=max(maxl,LEN[i]);
    68     int lf=0, rg=maxl-1;
    69     while(lf<=rg) {
    70         int mid=(lf+rg)>>1;
    71         if(check(mid)) rg=mid-1;
    72         else lf=mid+1;
    73     }
    74     printf("%d
    ",rg+1);
    75     return 0;
    76 }
    77 
    Tarjan并查集
     1 /**************************************************************
     2     Problem: 4326
     3     User: Doggu
     4     Language: C++
     5     Result: Accepted
     6     Time:9700 ms
     7     Memory:46452 kb
     8 ****************************************************************/
     9  
    10 #define PN "transport"
    11 #include <cstdio>
    12 #include <cstring>
    13 #include <algorithm>
    14 using namespace std;
    15 template<class T>inline void readin(T &res) {
    16     static char ch;while((ch=getchar())<'0'||ch>'9');
    17     res=ch-48;while((ch=getchar())>='0'&&ch<='9')res=(res<<1)+(res<<3)+ch-48;
    18 }
    19  
    20 const int N = 300000+10;
    21 const int M = 300000+10;
    22 struct EDGE {int v, upre, w;}g[N*2];
    23 int head[N], ne=0;
    24 inline void adde(int u,int v,int w) {g[++ne]=(EDGE){v,head[u],w},head[u]=ne;}
    25  
    26 int n, m, u, v, w, s, t;
    27  
    28 const int S = 19;
    29 int dep[N], anc[N][S+1], dis[N], edg[N], A[M], B[M], C[M], LEN[M];
    30 void DFS(int u,int fa) {
    31     anc[u][0]=fa;
    32     for( int j = 1; j <= S; j++ ) anc[u][j]=anc[anc[u][j-1]][j-1];
    33     for( int i = head[u]; i; i = g[i].upre ) {
    34         int v=g[i].v;
    35         if(v==fa) continue;
    36         edg[v]=g[i].w;dep[v]=dep[u]+1;dis[v]=dis[u]+g[i].w;DFS(v,u);
    37     }
    38 }
    39  
    40 int lca(int u,int v) {
    41     if(dep[u]<dep[v]) swap(u,v);
    42     for( int t=dep[u]-dep[v],p=0; t; t>>=1,p++ ) if(t&1) u=anc[u][p];
    43     if(u==v) return u;
    44     for( int p = S; anc[u][0]!=anc[v][0]; p-- ) if(anc[u][p]!=anc[v][p]) u=anc[u][p], v=anc[v][p];
    45     return anc[u][0];
    46 }
    47  
    48 int counter, maxl=0, flag[N], ans;
    49 void DFS1(int u,int fa) {
    50     for( int i = head[u]; i; i = g[i].upre ) {
    51         int v = g[i].v;
    52         if(v==fa) continue;
    53         DFS1(v,u);
    54         flag[u]+=flag[v];
    55     }
    56     if(flag[u]==counter) ans=max(ans,edg[u]);
    57 }
    58 bool check(int limit) {
    59     ans=0;counter=0;memset(flag,0,sizeof(flag));for( int i = 1; i <= m; i++ ) if(LEN[i]>limit) counter++, flag[A[i]]++, flag[B[i]]++, flag[C[i]]-=2;
    60     DFS1(1,1);return maxl-ans<=limit;
    61 }
    62  
    63 int main() {
    64     //freopen(PN".in","r",stdin);
    65     //freopen(PN".out","w",stdout);
    66     readin(n);readin(m);for( int i = 1; i < n; i++ ) {readin(u);readin(v);readin(w);adde(u,v,w);adde(v,u,w);}
    67     DFS(1,1);
    68     for( int i = 1; i <= m; i++ ) {
    69         readin(A[i]);readin(B[i]);C[i]=lca(A[i],B[i]);
    70         LEN[i]=dis[A[i]]+dis[B[i]]-dis[C[i]]*2;maxl=max(maxl,LEN[i]);
    71     }
    72     int lf=0, rg=maxl-1;
    73     while(lf<=rg) {
    74         int mid=(lf+rg)>>1;
    75         if(check(mid)) rg=mid-1;
    76         else lf=mid+1;
    77     }
    78     printf("%d
    ",rg+1);
    79     return 0;
    80 }
    ST表倍增

       不过,昶宇哥确实快炸了……我犯大不韪地交了一下他的,却发现早有人交过了……

    14 1182623 ddyyff 36952 KB 2992 MS C++ 4689 B 2015-12-05 09:31:34
    15 2139716(3) Doggu 36972 KB 2992 MS C++ 4689 B 2017-07-02 08:57:28

      

  • 相关阅读:
    perfnet错误 事件ID:2004 无法打开服务器服务。服务器性能数据将不会被返回。
    尝试加载 Oracle 客户端库时引发 BadImageFormatException。如果在安装 32 位 Oracle 客户端组件的情况下以 64 位模式运行,将出现此问题
    oracle从dmp文件做数据恢复
    python预科5--函数及lambda匿名函数
    pytest 运行SyntaxError: invalid syntax
    java自动化--testNG集成extentreports(好坑,编辑的时候样式好的,但是发布了就这鬼样子还不能上图)
    git 命令
    java 5
    java JsonMapper
    java springboot mybatis整合
  • 原文地址:https://www.cnblogs.com/Doggu/p/test20170701.html
Copyright © 2020-2023  润新知