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\n",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\n",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\n",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\n",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\n",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

  

posted @ 2017-07-01 20:46  Doggu  阅读(153)  评论(0编辑  收藏  举报