记次浙大月赛 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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

 补坑

----------------------------------------------------------

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 }
View Code

 

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 }
View Code

 

 

你可能感兴趣的:(ZOJ)