记次浙大月赛 134 - ZOJ Monthly, June 2014
虽做出的很少,也记录下来,留着以后来补。。浙大题目质量还是很高的
B
并查集的一些操作,同类和不同类我是根据到根节点距离的奇偶判断的,删点是直接新加一个点,记得福大月赛也做过类似的,并差集的这类关系题目还是比较常见的,有空深究一下。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 600010 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int fa[N],res[N],mp[N]; 18 int dis[N]; 19 int find(int x) 20 { 21 if(fa[x]!=x) 22 { 23 int ro = find(fa[x]); 24 dis[x]+=dis[fa[x]]; 25 return fa[x] = ro; 26 } 27 else 28 return x; 29 } 30 int main() 31 { 32 int n,m,i; 33 char s[10]; 34 while(scanf("%d%d",&n,&m)!=EOF) 35 { 36 for(i = 1; i <= n+m; i++) 37 { 38 fa[i] = i; 39 res[i] = 1; 40 mp[i] = i; 41 dis[i] = 0; 42 } 43 int g = n+1; 44 while(m--) 45 { 46 int x,y; 47 scanf("%s",s); 48 if(s[0]=='L') 49 { 50 scanf("%d%d",&x,&y); 51 x = mp[x]; 52 y = mp[y]; 53 int tx = find(x); 54 int ty = find(y); 55 if(tx!=ty) 56 { 57 fa[tx] = ty; 58 dis[tx] = (dis[x]+1+dis[y]);//合并时应根据两树上的节点距离来确定两树的根节点距离 59 res[ty]+=res[tx]; 60 } 61 } 62 else if(s[0]=='Q') 63 { 64 scanf("%d%d",&x,&y); 65 x = mp[x]; 66 y = mp[y]; 67 int tx = find(x); 68 int ty = find(y); 69 //cout<<tx<<" "<<ty<<endl; 70 if(tx!=ty) 71 { 72 printf("Unknown\n"); 73 continue; 74 } 75 if((dis[x]-dis[y])%2==0) 76 printf("Same\n"); 77 else 78 printf("Different\n"); 79 } 80 else if(s[0]=='S') 81 { 82 scanf("%d",&x); 83 x = mp[x]; 84 int tx = find(x); 85 printf("%d\n",res[tx]); 86 } 87 else 88 { 89 scanf("%d",&x); 90 int xx = mp[x]; 91 int tx = find(xx); 92 res[tx]-=1; 93 mp[x] = ++g; 94 } 95 } 96 } 97 return 0; 98 }
C
离散化一下,枚举所有值所在的区间段,从左到右走一遍,采用边删边走的形式。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 #include<map> 11 using namespace std; 12 #define N 100010 13 #define LL long long 14 #define INF 0xfffffff 15 const double eps = 1e-8; 16 const double pi = acos(-1.0); 17 const double inf = ~0u>>2; 18 map<int,int>f; 19 vector<int>ed[N]; 20 vector<int>dd[N]; 21 int c[N]; 22 int main() 23 { 24 int n,k,i,j; 25 while(scanf("%d%d",&n,&k)!=EOF) 26 { 27 f.clear(); 28 int g = 0; 29 for(i = 1; i <= n; i++) 30 { 31 ed[i].clear(); 32 dd[i].clear(); 33 } 34 for(i = 1; i <=n ;i++) 35 { 36 scanf("%d",&c[i]); 37 if(!f[c[i]]) f[c[i]] = ++g; 38 if(i==1) 39 { 40 dd[f[c[i]]].push_back(i); 41 continue; 42 } 43 int tg = f[c[i-1]]; 44 if(c[i]!=c[i-1]) 45 { 46 ed[tg].push_back(i-1); 47 dd[f[c[i]]].push_back(i); 48 } 49 } 50 ed[f[c[n]]].push_back(n); 51 int ans = 0; 52 for(i = 1; i <= g; i++) 53 { 54 int tk = 0,st=0,ss=0; 55 ss += ed[i][0]-dd[i][0]+1; 56 ans = max(ans,ss); 57 58 for(j = 1 ;j < ed[i].size() ; j++) 59 { 60 tk+=(dd[i][j]-ed[i][j-1]-1); 61 ss+=(ed[i][j]-dd[i][j]+1); 62 while(tk>k&&st<j) 63 { 64 tk-=(dd[i][st+1]-ed[i][st]-1); 65 ss-=(ed[i][st]-dd[i][st]+1); 66 st++; 67 } 68 69 ans = max(ans,ss); 70 } 71 } 72 printf("%d\n",ans); 73 } 74 return 0; 75 }
F
这题有点逗,看了半个多小时终于看懂了啥意思,然后。。一份更逗的AC代码,全部输出1.
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 100000 12 #define LL long long 13 #define INF 0xfffffff 14 const double eps = 1e-8; 15 const double pi = acos(-1.0); 16 const double inf = ~0u>>2; 17 int main() 18 { 19 int t,b,e; 20 cin>>t; 21 while(t--) 22 { 23 cin>>b>>e; 24 cout<<"1\n"; 25 } 26 return 0; 27 }
补坑
----------------------------------------------------------
D
dp,今天周赛鹏队把月赛题放出来了,上面3个都A过了,就去看这题。
这题着重点要放在有多少个不同的字母上面,用dp[i][g]表示有当前走了i步且有g个字母不同,往后递推步数,因为每次会变m个位置,那么可以枚举当前g个里面变了j个,那么len-g里面肯定要变m-j个。
那么久可以写出递推方程dp[i-g+m-g][j] = dp[i][j]*C(g,j)*C(len-g,m-j) 注意下边界问题。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 using namespace std; 11 #define N 101 12 #define LL long long 13 #define INF 0xfffffff 14 #define mod 1000000009 15 const double eps = 1e-8; 16 const double pi = acos(-1.0); 17 const double inf = ~0u>>2; 18 char s1[N],s2[N]; 19 LL dp[N][N],c[N][N]; 20 void init() 21 { 22 for(int i=0;i<=100;i++) 23 for(int j=0;j<=i;j++) 24 if(!j || i==j) 25 c[i][j]=1; 26 else 27 c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod; 28 } 29 int main() 30 { 31 int n,m,k,i,j,g; 32 init(); 33 while(scanf("%d%d%d",&n,&k,&m)!=EOF) 34 { 35 memset(dp,0,sizeof(dp)); 36 cin>>s1>>s2; 37 if(strlen(s1)!=strlen(s2)||strlen(s1)<m) 38 { 39 puts("0"); 40 continue; 41 } 42 int len = strlen(s1); 43 int num = 0; 44 for(i =0 ;i < len ; i++) 45 if(s1[i]!=s2[i]) 46 num++; 47 dp[0][num] = 1; 48 for(i = 1; i <= k ; i++) 49 { 50 for(g = 0; g <= len; g++) 51 for(j = 0 ; j <= min(g,m) ;j++) 52 { 53 if(len-g<m-j) continue; 54 // cout<<i<<" "<<j<<endl; 55 dp[i][g-j+(m-j)]=(dp[i][g-j+(m-j)]+((dp[i-1][g]*c[g][j])%mod*c[len-g][m-j])%mod)%mod; 56 // if(i==2&&j==0) 57 // { 58 // cout<<c[num-g][m-j]<<" "<<num-g<<" "<<m-j<<endl; 59 // cout<<i<<" "<<g-j+m-j<<" "<<dp[i][g-j+m-j]<<endl; 60 // } 61 } 62 } 63 cout<<dp[k][0]<<endl; 64 } 65 return 0; 66 }
H
tarjan缩点,然后找一个最长路,这个可以用topo思想来找最长的。
1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queue> 9 #include<set> 10 #include<stack> 11 using namespace std; 12 #define N 100010 13 #define LL long long 14 #define INF 0xfffffff 15 const double eps = 1e-8; 16 const double pi = acos(-1.0); 17 const double inf = ~0u>>2; 18 vector<int>ed[N]; 19 vector<int>dd[2]; 20 vector<int>ee[N]; 21 int de[N],nn[N],dis[N]; 22 bool vis[N]; 23 int pre[N],lowlink[N],sccno[N],dfs_lock,scc_cnt; 24 stack<int>S; 25 void dfs(int u) 26 { 27 pre[u] = lowlink[u] = ++dfs_lock; 28 S.push(u); 29 for(int i = 0 ;i < (int)ed[u].size() ; i++) 30 { 31 int v = ed[u][i]; 32 if(!pre[v]) 33 { 34 dfs(v); 35 lowlink[u] = min(lowlink[u],lowlink[v]); 36 } 37 else if(!sccno[v]) 38 lowlink[u] = min(lowlink[u],pre[v]); 39 } 40 if(lowlink[u]==pre[u]) 41 { 42 scc_cnt++; 43 int g = 0; 44 for(;;) 45 { 46 int x = S.top();S.pop(); 47 sccno[x] = scc_cnt; 48 g++; 49 if(x==u) break; 50 } 51 nn[scc_cnt] = g; 52 } 53 } 54 void find_scc(int n) 55 { 56 dfs_lock = scc_cnt = 0; 57 memset(sccno,0,sizeof(sccno)); 58 memset(pre,0,sizeof(pre)); 59 for(int i = 0 ;i < n; i++) 60 if(!pre[i]) dfs(i); 61 } 62 int find() 63 { 64 int i; 65 for(i = 1 ;i <= scc_cnt ; i++) 66 dis[i] = 0; 67 queue<int>q; 68 for(i = 1 ;i <= scc_cnt ; i++) 69 { 70 if(de[i]==0) 71 { 72 q.push(i); 73 dis[i] = nn[i]; 74 } 75 } 76 while(!q.empty()) 77 { 78 int tu = q.front(); 79 q.pop(); 80 for(i = 0; i < ee[tu].size() ; i++) 81 { 82 int v = ee[tu][i]; 83 dis[v] = max(dis[v],dis[tu]+nn[v]); 84 de[v]--; 85 if(de[v]==0) 86 q.push(v); 87 } 88 } 89 int ans = 0; 90 for(i = 1 ; i <= scc_cnt ; i++) 91 ans = max(ans,dis[i]); 92 return ans; 93 } 94 int main() 95 { 96 int i,m,n,j; 97 while(scanf("%d%d",&n,&m)!=EOF) 98 { 99 memset(de,0,sizeof(de)); 100 for(i = 0 ;i <= n ;i++) 101 { 102 ed[i].clear(); 103 ee[i].clear(); 104 } 105 dd[0].clear(); 106 dd[1].clear(); 107 for(i = 1; i <= m ;i++) 108 { 109 int u,v; 110 scanf("%d%d",&u,&v);u--,v--; 111 ed[u].push_back(v); 112 } 113 find_scc(n); 114 for(i = 0; i < n ;i++) 115 { 116 for(j = 0;j < (int)ed[i].size() ; j++) 117 { 118 int v = ed[i][j]; 119 if(sccno[i]!=sccno[v]) 120 { 121 vector<int>::iterator it; 122 int tu = sccno[i],tv = sccno[v]; 123 // it = lower_bound(ee[tu].begin(),ee[tu].end(),tv); 124 // if(it==ee[tu].end()||(*it)!=tv) 125 // { 126 ee[tu].push_back(tv); 127 de[tv]++; 128 // } 129 } 130 } 131 } 132 printf("%d\n",find()); 133 } 134 return 0; 135 }