比赛链接:https://vjudge.net/contest/378025#overview

这场在期末考试前打的,后面一直复习期末考试去了,今天才补完。感觉现场赛的题都挺难的,还是自己太菜了。

E - Cats and Fish

题意:有n只猫,m条鱼,每只猫都有吃鱼的时间,吃的时候相对少的优先。问x分钟后,有多少条鱼没被吃,有多少鱼正在被吃。用优先队列模拟过程即可。

1 #include

2 #include

3 #include

4 using namespace std;

5 struct node

6 {

7 int v,w;

8 bool operator<(const node&b)const

9 {

10 if(w==b.w)return v>b.v;

11 return w>b.w;

12 }

13 } temp;

14 int n,m,x,c,ans;

15 int main()

16 {

17 while(~scanf("%d%d%d",&m,&n,&x))

18 {

19 ans=0;

20 priority_queueq;

21 for(int i=1; i<=n; i++)

22 {

23 scanf("%d",&c);

24 q.push(node{c,0});

25 }

26 while(m --)

27 {

28 if(q.top().w >= x) break;

29 auto t = q.top();

30 q.pop();

31 t.w += t.v;

32 q.push(t);

33 }

34 while(!q.empty())

35 {

36 auto t = q.top();

37 q.pop();

38 if(t.w > x)

39 ans ++;

40 }

41 printf("%d %d\n", m + 1, ans);

42 }

43 return 0;

44 }

View Code

F - Secret Poems

题意:按照矩阵模拟。

1 #include

2 #include

3 #include

4 #include

5 using namespace std;

6 typedef long long ll;

7 const int maxn = 110;

8 char s[maxn][maxn];

9 char p[maxn][maxn];

10 int vis[maxn][maxn];

11 char c[maxn*maxn];

12 int x,y,tot,n;

13 int cnt;

14 int main()

15 {

16 while(cin>>n)

17 {

18 memset(s,0,sizeof s);

19 memset(p,0,sizeof p);

20 memset(c,0,sizeof c);

21 for(int i=0; i

22 for(int j=0; j

23 cin>>s[i][j];

24 p[0][0]=s[0][0];

25 x=0;y=0;

26 cnt = 0; // 折线读取

27 for(int i=0; i<2*n - 1; i++)

28 {

29 if(i%2)

30 {

31 for(int j=i; j>=0; j--)

32 if(i-j

33 c[cnt++] =s[i-j][j];

34 }

35 else

36 {

37 for(int j=0; j<=i; j++)

38 if(i-j

39 c[cnt++] =s[i-j][j];

40 }

41 }

42 tot=0;

43 while(tot

44 {

45 while(y+1

46 p[x][++y]=c[++tot];

47 while(x+1

48 p[++x][y]=c[++tot];

49 while(y-1>=0&&!p[x][y-1])//左

50 p[x][--y]=c[++tot];

51 while(x-1>=0&&!p[x-1][y])//上

52 p[--x][y]=c[++tot];

53 }

54 for(int i=0; i

55 {

56 for(int j=0; j

57 cout<

58 cout<

59 }

60 }

61 return 0;

62 }

View Code

J - Pangu and Stones

题意:给n堆石头,每堆石头有一定的重量,每次合并的花费是重量之和,每次只能合并l-r堆变成1堆,求最小的花费,若不存在输出0。

区间Dp,用dp[i][j][k]表示i到j分成k堆。以为只能变成1,所以每次必然是用1去更新最后一维k。

1 #include

2 using namespace std;

3

4 const int N = 110;

5 const int INF = 0x3f3f3f3f;

6 int n, l, r;

7 int f[N][N][N];

8 int a[N];

9 int sum[N];

10 int main()

11 {

12 while(scanf("%d%d%d", &n, &l, &r)!= EOF)

13 {

14 for (int i = 1; i <= n; i ++)

15 for (int j = 1; j <= n; j ++)

16 for (int k = 1; k <= n; k ++)

17 f[i][j][k] = INF;

18 for (int i = 1; i <= n; i ++)

19 {

20 scanf("%d", &a[i]);

21 sum[i] = sum[i - 1] + a[i];

22 f[i][i][1] = 0;

23 }

24 for (int len = 2; len <= n; len ++)

25 {

26 for (int i = 1; i + len - 1 <= n; i ++)

27 {

28 int j = i + len - 1;

29 f[i][j][len] = 0;

30 for (int k = 2; k <= len; k ++)

31 {

32 for (int p = i; p < j; p ++)

33 {

34 f[i][j][k] = min(f[i][j][k], f[i][p][1] + f[p + 1][j][k - 1]);

35 }

36 if(k >= l && k <= r)

37 f[i][j][1] = min(f[i][j][1], f[i][j][k] + sum[j] - sum[i - 1]);

38 }

39

40 }

41 }

42 if(f[1][n][1] == 0x3f3f3f3f) f[1][n][1] = 0;

43 printf("%d\n", f[1][n][1]);

44 }

45 }

View Code

C - Graph

题意:给你一个n个顶点,m条边的无向图,q次询问。问你l到r之间,有多少不同的路径是联通的。考虑一次询问,就是并查集维护下联通块的数量,考虑是很多询问,用莫队+可删除并查集(倒着模拟一遍)。

1 #include

2 using namespace std;

3 const int N = 1e5 + 10;

4

5 int T;

6 int n, m, t;

7 vectorg[N];

8 int p[N], cnt[N];

9 int ans[N];

10 int size, belong[N], L[N], R[N], num;

11 stackst;

12 int find(int x)

13 {

14 if(x == p[x]) return x;

15 return find(p[x]);

16 }

17

18 struct query{

19 int l, r, id;

20 }q[N];

21

22 int cmp(query a, query b)

23 {

24 return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : a.r < b.r;

25 }

26 int tmp;

27 void merge(int x,int y,int flag)

28 {

29 int fx = find(x),fy=find(y);

30 if(fx==fy)

31 return ;

32 if(cnt[fx] > cnt[fy])

33 {

34 swap(x,y);

35 swap(fx,fy);

36 }

37 tmp += cnt[fx]*cnt[fy];

38 p[fx]=fy;

39 cnt[fy]+=cnt[fx];

40 if(!flag)

41 st.push(fx);

42 }

43

44 int main()

45 {

46 scanf("%d", &T);

47 while(T --)

48 {

49 scanf("%d%d%d", &n, &m, &t);

50 size = sqrt(n);

51 num = (n - 1)/ size + 1;

52 while(!st.empty()) st.pop();

53 for (int i = 1; i <= n; i ++)

54 {

55 g[i].clear();

56 belong[i] = (i - 1) / size + 1;

57 }

58 for (int i = 1; i <= num; i ++)

59 L[i] = (i - 1) * size + 1, R[i] = i * size;

60 R[num] = n;

61 for (int i = 1; i <= m; i ++)

62 {

63 int x, y;

64 scanf("%d%d", &x, &y);

65 g[x].push_back(y), g[y].push_back(x);

66 }

67 for (int i = 1; i <= t; i ++)

68 {

69 scanf("%d%d", &q[i].l, &q[i].r);

70 q[i].id = i;

71 }

72 sort(q + 1, q + t + 1, cmp);

73 int now = 0;

74 int posr = 0, posl = 0;

75 for(int i=1;i<=t;i++)

76 {

77 if(belong[q[i].l]!=belong[q[i-1].l])

78 {

79 posr=posl=R[belong[q[i].l]];

80 for(int j=1;j<=n;j++)

81 {

82 p[j]=j;

83 cnt[j]=1;

84 }

85 tmp = 0;

86 }

87 while(posr

88 {

89 posr++;

90 for (auto j : g[posr])

91 {

92 if(j>R[belong[q[i].l]]&&j<=q[i].r)

93 merge(posr,j,1);

94 }

95 }

96 now = tmp;

97 for(posl=min(q[i].r,R[belong[q[i].l]]);posl>=q[i].l;posl--)

98 {

99 for (auto j : g[posl])

100 {

101 if(j>=q[i].l&&j<=q[i].r)

102 merge(posl,j,0);

103 }

104 }

105 ans[q[i].id]=tmp;

106 while(!st.empty())

107 {

108 int u=st.top();

109 st.pop();

110 cnt[p[u]]-=cnt[u];

111 p[u]=u;

112 }

113 tmp = now;

114 posl=R[belong[q[i].l]];

115 }

116 for (int i = 1; i <= t; i ++)

117 printf("%d\n", ans[i]);

118 }

119 }

View Code