Ural Sport Programming Championship 2015

A - The First Day at School

题目描述:给出课程安排,打印一个课程表。

solution

暴力模拟。

B - Maths

题目描述:给定一个数\(n\),找出一个序列\(a_i\)满足\(\forall i \in [2, n], \sum_{j=1}^{j \leq i} a_j\) 有\(a_i\)个约数。

solution

暴力搜索,发现和不会超过\(2 \times 10^6\), 数字不会超过\(200\),而且直接搜索即可很快求出答案。

时间复杂度:\(O(能过)\)

C - History

题目描述:求出从\(A\)年到\(B\)年中有\(1\)~\(12\)个黑色星期五的分别有多少年。

solution

显然有循环,模拟一下发现2800年左右有循环,因此只需要求出循环中每一年有多少个黑色星期五,然后求答案,求一下前缀和即可。

时间复杂度:\(O(2800 \times 12)\)

D - Chemistry

题目描述:给出\(n\)个杯子,每个杯子有一升的水,每次从一个杯子向另一个杯子倒水,使得后一个杯子的水变成原来的两倍,求出一种操作方案,使得最终有一个杯子有\(m\)升水,或无解。

solution

不会,本来想着好像二分那样弄就行,但发现会有副产品利用的情况,而且情况有些复杂。

E - 3D-modeling

题目描述:给定空间中的两条线段,问是否存在一条直线,使得一条线段绕直线转某个角度即可得到另一条直线,求出这条直线和对应的角度。

solution

不会

F - Physics

题目描述:有两个\(v(t)\)函数\(v_1, v_2\),这两个函数都是折线函数,令\(h(t)=max(v_1(t), v_2(t)), g(t)=min(v_1(t), v_2(t))\),给出\(h(t), g(t)\)的起点、终点、转折点,求出\(v_1(t), v_2(t)\),使得两个函数所代表的位移相等。\(v_1, v_2\)重合点不超过\(30\)个。

solution

求出所有的重合点,假设开始时\(v_1=h, v_2=g\),而只有遇到重合点的时候,\(v_1, v_2\)才有可能交换,即重合点将函数分成了若干段,每一段中的函数不能相交,因此可以分开前后两个部分进行搜索,然后判断是否存在一种方案使得合起来的位移等于总位移的一半。

注意:有可能\(h(t1) \neq g(t1)\),但\(v_1(t1) = v_2(t1)\)

时间复杂度:\(O(2 \times 2^{15})\)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long LL;
  4. const int maxn=int(2e6)+100;
  5. int T, n, m;
  6. pair<int, int> h[maxn], g[maxn], tmp[maxn];
  7. vector< pair<int, int> > v1, v2, cp;
  8. map<LL, int> cnt;
  9. LL sumh[maxn], sumg[maxn];
  10. int block;
  11. bool vis[maxn];
  12. void read()
  13. {
  14. scanf("%d", &T);
  15. scanf("%d", &n);
  16. for (int i=1; i<=n; ++i)
  17. scanf("%d%d" , &h[i].first, &h[i].second);
  18. scanf("%d", &m);
  19. for (int i=1; i<=m; ++i)
  20. scanf("%d%d", &g[i].first, &g[i].second);
  21. }
  22. void crosspoint()
  23. {
  24. for (int i=1; i<=n; ++i) tmp[i]=h[i];
  25. int tmpn=n;
  26. n=1;
  27. for (int i=2; i<=tmpn; ++i)
  28. for (int j=tmp[i-1].first+1; j<=tmp[i].first; ++j)
  29. if (LL(j-tmp[i-1].first)*(tmp[i].second-tmp[i-1].second)%(tmp[i].first-tmp[i-1].first)==0)
  30. h[++n]=make_pair(j, LL(j-tmp[i-1].first)*(tmp[i].second-tmp[i-1].second)/(tmp[i].first-tmp[i-1].first)+tmp[i-1].second);
  31. /*
  32. puts("h:");
  33. for (int i=1; i<=n; ++i) printf("%d %d\n", h[i].first, h[i].second);
  34. */
  35. for (int i=1; i<=m; ++i) tmp[i]=g[i];
  36. int tmpm=m;
  37. m=1;
  38. for (int i=2; i<=tmpm; ++i)
  39. for (int j=tmp[i-1].first+1; j<=tmp[i].first; ++j)
  40. if (LL(j-tmp[i-1].first)*(tmp[i].second-tmp[i-1].second)%(tmp[i].first-tmp[i-1].first)==0)
  41. g[++m]=make_pair(j, LL(j-tmp[i-1].first)*(tmp[i].second-tmp[i-1].second)/(tmp[i].first-tmp[i-1].first)+tmp[i-1].second);
  42. /*
  43. puts("g:");
  44. for (int i=1; i<=m; ++i) printf("%d %d\n", g[i].first, g[i].second);
  45. */
  46. for (int i=1, j=1; i<=n && j<=m; ++i)
  47. {
  48. while (j<=m && g[j].first<h[i].first) ++j;
  49. if (j>m) continue;
  50. if (h[i].first==g[j].first && h[i].second==g[j].second)
  51. cp.push_back(h[i]);
  52. }
  53. if (h[n].second!=g[m].second) cp.push_back(h[n]);
  54. /*
  55. puts("cp:");
  56. for (auto &i:cp) printf("%d %d\n", i.first, i.second);
  57. */
  58. }
  59. void calc_sum()
  60. {
  61. block=cp.size();
  62. LL s=0;
  63. for (int i=2, j=0; i<=n; ++i)
  64. {
  65. while (j<cp.size() && cp[j].first<h[i].first) ++j;
  66. s+=LL(h[i-1].second+h[i].second)*(h[i].first-h[i-1].first);
  67. if (j>=cp.size()) continue;
  68. if (cp[j].first==h[i].first) sumh[j]=s, s=0;
  69. }
  70. s=0;
  71. for (int i=2, j=0; i<=m; ++i)
  72. {
  73. while (j<cp.size() && cp[j].first<g[i].first) ++j;
  74. s+=LL(g[i-1].second+g[i].second)*(g[i].first-g[i-1].first);
  75. if (j>=cp.size()) continue;
  76. if (cp[j].first==g[i].first) sumg[j]=s, s=0;
  77. }
  78. /*
  79. for (int i=0; i<block; ++i) printf("%lld ", sumh[i]);
  80. for (int i=0; i<block; ++i) printf("%lld ", sumg[i]);
  81. */
  82. }
  83. inline LL det(pair<int, int> b, pair<int, int> c, pair<int, int> o)
  84. {
  85. return (b.first-o.first)*(c.second-o.second)-(b.second-o.second)*(c.first-o.first);
  86. }
  87. void print(LL sett)
  88. {
  89. for (int i=0, j=1, k=1; i<block; ++i)
  90. {
  91. if (sett>>i & 1)
  92. {
  93. while (j<=n && h[j].first<=cp[i].first) v1.push_back(h[j++]);
  94. while (k<=m && g[k].first<=cp[i].first) v2.push_back(g[k++]);
  95. }
  96. else
  97. {
  98. while (j<=n && h[j].first<=cp[i].first) v2.push_back(h[j++]);
  99. while (k<=m && g[k].first<=cp[i].first) v1.push_back(g[k++]);
  100. }
  101. }
  102. for (int i=0; i<v1.size(); ++i) vis[i]=true;
  103. for (int i=2; i<v1.size(); ++i)
  104. if (det(v1[i-2], v1[i-1], v1[i])==0) vis[i-1]=false;
  105. int ans=0;
  106. for (int i=0; i<v1.size(); ++i) ans+=vis[i];
  107. printf("%d\n", ans);
  108. for (int i=0; i<v1.size(); ++i)
  109. if (vis[i]) printf("%d %d\n", v1[i].first, v1[i].second);
  110. for (int i=0; i<v2.size(); ++i) vis[i]=true;
  111. for (int i=2; i<v2.size(); ++i)
  112. if (det(v2[i-2], v2[i-1], v2[i])==0) vis[i-1]=false;
  113. ans=0;
  114. for (int i=0; i<v2.size(); ++i) ans+=vis[i];
  115. printf("%d\n", ans);
  116. for (int i=0; i<v2.size(); ++i)
  117. if (vis[i]) printf("%d %d\n", v2[i].first, v2[i].second);
  118. }
  119. void solve()
  120. {
  121. crosspoint();
  122. calc_sum();
  123. LL total=0;
  124. for (int i=0; i<block; ++i) total+=sumh[i]+sumg[i];
  125. total/=2;
  126. for (int i=0; i<1<<(block/2); ++i)
  127. {
  128. LL s=0;
  129. for (int j=0; j<block/2; ++j)
  130. if (i>>j & 1) s+=sumh[j];
  131. else s+=sumg[j];
  132. cnt[s]=i;
  133. }
  134. for (int i=0; i<1<<(block-block/2); ++i)
  135. {
  136. LL s=0;
  137. for (int j=0; j<block-block/2; ++j)
  138. if (i>>j & 1) s+=sumh[block/2+j];
  139. else s+=sumg[block/2+j];
  140. if (cnt.count(total-s))
  141. {
  142. print(cnt[total-s]|(i<<(block/2)));
  143. return;
  144. }
  145. }
  146. }
  147. int main()
  148. {
  149. read();
  150. solve();
  151. return 0;
  152. }

G - Physical Education

题目描述:给定一个数字\(n\),将\(1\)到\(n\)重新排序:按各个位的数字的和从小到大排,相同的按预案数字从小到大排,问排序后的位置与原数字一样的数有多少个。

solution

先做一个数位\(dp\),求出各个位的数字的和各有多少个,然后按这个进行分组,每一组最多只有可能有一个数字的位置与原数字的位置相同,这是因为在同一组中,相邻的数字的差事大于\(1\)的,因此不可能有两个数字的位置与原位置相同,如果有,那么这两个位置之间的数字的差必须都是\(1\)。

如果用新数列减去旧数列,则在同一组中,得到的数列是递增的,而我们要找的是是否存在一个等于零的位置,如果存在,则答案加一。这里可以用二分,每次二分用数位\(dp\)求出和与当前组的和一样的,小于等于某个数的数字有多少个,就可以判断是否存在。

时间复杂度:\(O(81 \times log(10^9) \times 9*10*81)\)

H - Biology

题目描述:在平面上找出\(16\)个点,然后构成一个平面图,使得该图中的简单环超过\(3\times10^5\)个。

solution

直接上图。

J - Urban Geography

题目描述:给出一个图,\(n\)个点,\(m\)条边,选择一些边,使得构成一颗生成树,而且选择的边的权值的最大值与最小值的差最小,输出方案。

solution

用\(LCT\)维护生成树,将边从小到大排序,然后逐条边添加进去,每次添加后把环里面的最小边删掉,更新答案。

时间复杂度:\(O(nlogn)\)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=int(5e4)+100;
  4. const int inf=0x7fffffff;
  5. struct node
  6. {
  7. node *son[2], *fa;
  8. node *maxid;
  9. int value, num;
  10. bool reverse;
  11. node()
  12. {
  13. son[0]=son[1]=fa=NULL;
  14. maxid=NULL;
  15. value=inf;
  16. num=0;
  17. reverse=false;
  18. }
  19. void update()
  20. {
  21. maxid=this;
  22. if (son[0] && son[0]->maxid->value<maxid->value) maxid=son[0]->maxid;
  23. if (son[1] && son[1]->maxid->value<maxid->value) maxid=son[1]->maxid;
  24. }
  25. void down()
  26. {
  27. if (!reverse) return;
  28. if (son[0])
  29. {
  30. son[0]->reverse^=1;
  31. swap(son[0]->son[0], son[0]->son[1]);
  32. }
  33. if (son[1])
  34. {
  35. son[1]->reverse^=1;
  36. swap(son[1]->son[0], son[1]->son[1]);
  37. }
  38. reverse=false;
  39. }
  40. void rotate(int id)
  41. {
  42. node *y=fa;
  43. node *z=y->fa;
  44. fa=z;
  45. if (z && (z->son[0]==y || z->son[1]==y)) z->son[z->son[1]==y]=this;
  46. y->son[id]=son[id^1];
  47. if (son[id^1]) son[id^1]->fa=y;
  48. son[id^1]=y;
  49. y->fa=this;
  50. y->update();
  51. update();
  52. }
  53. void splay()
  54. {
  55. node *x=this;
  56. while (x->fa && (x->fa->son[0]==x || x->fa->son[1]==x))
  57. {
  58. node *y=x->fa;
  59. node *z=y->fa;
  60. if (z && (z->son[0]==y || z->son[1]==y)) z->down();
  61. y->down(); x->down();
  62. if (!z || (z->son[0]!=y && z->son[1]!=y)) x->rotate(y->son[1]==x);
  63. else
  64. {
  65. bool L=z->son[1]==y, R=y->son[1]==x;
  66. if (L^R) x->rotate(R), x->rotate(L);
  67. else y->rotate(L), x->rotate(R);
  68. }
  69. }
  70. x->down();
  71. x->update();
  72. }
  73. node *expose()
  74. {
  75. node *x=this;
  76. node *y=NULL;
  77. for (; x!=NULL; y=x, x=x->fa)
  78. {
  79. x->splay();
  80. x->son[1]=y;
  81. x->update();
  82. }
  83. return y;
  84. }
  85. node *askroot()
  86. {
  87. node *x=expose();
  88. while (x->son[0]) x=x->son[0];
  89. x->splay();
  90. return x;
  91. }
  92. void evert()
  93. {
  94. expose();
  95. splay();
  96. reverse=true;
  97. swap(son[0], son[1]);
  98. }
  99. void cut(node *x, node *y)
  100. {
  101. x->evert();
  102. y->expose();
  103. splay();
  104. x->fa=y->fa=NULL;
  105. }
  106. void clear()
  107. {
  108. son[0]=son[1]=fa=NULL;
  109. maxid=NULL;
  110. value=inf;
  111. num=0;
  112. reverse=false;
  113. }
  114. };
  115. struct LINK
  116. {
  117. int x, y, dis;
  118. int num;
  119. bool operator < (const LINK b) const
  120. {
  121. return dis<b.dis;
  122. }
  123. };
  124. int n, m;
  125. LINK edge[maxn];
  126. node tree[maxn*2];
  127. set< pair<int, int> > len;
  128. bool vis[maxn];
  129. void read()
  130. {
  131. scanf("%d%d", &n, &m);
  132. for (int i=1; i<=m; ++i)
  133. {
  134. edge[i].num=i;
  135. scanf("%d%d%d", &edge[i].x, &edge[i].y, &edge[i].dis);
  136. }
  137. }
  138. node *askmin(node *x, node *y)
  139. {
  140. x->evert();
  141. y->expose();
  142. x->splay();
  143. return x->maxid;
  144. }
  145. void connect(node *x, node *y, int v, int idx)
  146. {
  147. node *z=tree+n+idx;
  148. z->value=v;
  149. z->num=idx;
  150. z->fa=x;
  151. y->evert();
  152. y->fa=z;
  153. }
  154. void solve()
  155. {
  156. sort(edge+1, edge+1+m);
  157. int block=n;
  158. int minnum=inf;
  159. int ans;
  160. for (int i=1; i<=m; ++i)
  161. {
  162. node *u=tree+edge[i].x;
  163. node *v=tree+edge[i].y;
  164. len.insert(make_pair(edge[i].dis, i));
  165. if (u->askroot()!=v->askroot())
  166. connect(u, v, edge[i].dis, i), block--;
  167. else
  168. {
  169. node *x=askmin(u, v);
  170. len.erase(make_pair(x->value, x->num));
  171. x->cut(tree+edge[x->num].x, tree+edge[x->num].y);
  172. connect(u, v, edge[i].dis, i);
  173. }
  174. if (block!=1) continue;
  175. int tmp=len.begin()->first;
  176. if (edge[i].dis-tmp<minnum)
  177. {
  178. minnum=edge[i].dis-tmp;
  179. ans=i;
  180. }
  181. }
  182. for (int i=1; i<=n+m; ++i) (tree+i)->clear();
  183. for (int i=1; i<=ans; ++i)
  184. {
  185. node *u=tree+edge[i].x;
  186. node *v=tree+edge[i].y;
  187. vis[i]=true;
  188. if (u->askroot()!=v->askroot())
  189. connect(u, v, edge[i].dis, i), block--;
  190. else
  191. {
  192. node *x=askmin(u, v);
  193. x->cut(tree+edge[x->num].x, tree+edge[x->num].y);
  194. vis[x->num]=false;
  195. connect(u, v, edge[i].dis, i);
  196. }
  197. }
  198. for (int i=1; i<=m; ++i)
  199. if (vis[i]) printf("%d ", edge[i].num);
  200. }
  201. int main()
  202. {
  203. read();
  204. solve();
  205. return 0;
  206. }

K - Scholarship

solution

按题目说的做。

Ural Sport Programming Championship 2015的更多相关文章

  1. German Collegiate Programming Contest 2015 计蒜课

    // Change of Scenery 1 #include <iostream> #include <cstdio> #include <algorithm> ...

  2. Nordic Collegiate Programming Contest 2015​ B. Bell Ringing

    Method ringing is used to ring bells in churches, particularly in England. Suppose there are 6 bells ...

  3. Nordic Collegiate Programming Contest 2015​ G. Goblin Garden Guards

    In an unprecedented turn of events, goblins recently launched an invasion against the Nedewsian city ...

  4. Nordic Collegiate Programming Contest 2015​ E. Entertainment Box

    Ada, Bertrand and Charles often argue over which TV shows to watch, and to avoid some of their fight ...

  5. Nordic Collegiate Programming Contest 2015​ D. Disastrous Downtime

    You're investigating what happened when one of your computer systems recently broke down. So far you ...

  6. 2019-2020 10th BSUIR Open Programming Championship. Semifinal

    2019-2020 10th BSUIR Open Programming Championship. Semifinal GYM链接https://codeforces.com/gym/103637 ...

  7. URAL 1227 Rally Championship(树的直径)(无向图判环)

    1227. Rally Championship Time limit: 1.0 secondMemory limit: 64 MB A high-level international rally ...

  8. Gym100814B Gym100814F Gym100814I(异或) ACM International Collegiate Programming Contest, Egyptian Collegiate Programming Contest (2015) Arab Academy for Science and Technology

    今日份的训练题解,今天写出来的题没有昨天多,可能是因为有些事吧... Gym100814B 这个题就是老师改卷子,忘带标准答案了,但是他改了一部分卷子,并且确定自己改的卷子没出错,他想从改过的卷子里把 ...

  9. ACM Arabella Collegiate Programming Contest 2015 F. Palindrome 并查集

    题目链接:http://codeforces.com/gym/100676/attachments 题意: 给一个字符串,有一些约束条件,两个位置要相同,有一些是问号,求最后有多少种方案回文? 分析: ...

随机推荐

  1. 转---秒杀多线程第五篇 经典线程同步 关键段CS

    上一篇<秒杀多线程第四篇 一个经典的多线程同步问题>提出了一个经典的多线程同步互斥问题,本篇将用关键段CRITICAL_SECTION来尝试解决这个问题. 本文首先介绍下如何使用关键段,然 ...

  2. OSPF协议介绍及配置 (上)

    OSPF协议介绍及配置 (上) 一.OSPF概述 回顾一下距离矢量路由协议的工作原理:运行距离矢量路由协议的路由器周期性的泛洪自己的路由表,通过路由的交互,每台路由器都从相邻的路由器学习到路由,并且加 ...

  3. [BZOJ1195]最短母串

    1195: [HNOI2006]最短母串 Time Limit: 10 Sec  Memory Limit: 32 MB Description 给定n个字符串(S1,S2,„,Sn),要求找到一个最 ...

  4. Django之form表单提交并验证

    1.提交的时候会报错 2. 需要在setting里面注释掉一句话,关闭跨站请求检查. 3. 注释掉以后,理论上就不报错了.可我还是卡壳了. 4. 通过在网上找方法,修复错误. 原因:表单action字 ...

  5. unity3D 涂涂乐使用shader实现上色效果

    unity3D 涂涂乐使用shader实现上色效果 之前我博文里面发过一个简单的通过截图方式来实现的模型上色方法,但是那个方法不合适商用,因为你需要对的很准确才可以把贴图完美截取下来,只要你手抖了一下 ...

  6. Linux系统启动详解(一)

    本篇主要以Centos为例,讲述整个Linux系统启动过程,包括了grub引导,initramfs流程,/sbin/init执行rc.sysinit及rc的大体流程. 另外,本篇有一个实例来说明,将整 ...

  7. mac os 启动服务命令 launchctl

    参考苹果开发者网址 https://developer.apple.com/library/mac/documentation/MacOSX/Conceptual/BPSystemStartup/Ch ...

  8. 解题:SCOI 2008 天平

    题面 我们很容易想到差分约束,但是我们建出来图之后好像并不好下手,因为我们只能得到砝码间的大小关系,并不能容易地得到每个砝码的具体重量. 于是我们有了一种神奇的思路:既然得不到具体重量我们就不求具体重 ...

  9. 【bzoj3170】[Tjoi2013]松鼠聚会

    3170: [Tjoi2013]松鼠聚会 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1670  Solved: 885[Submit][Statu ...

  10. shell中的引用

    By francis_hao    Mar 31,2018   引用,用来移除某个字符或单词对于shell的特殊含义 每个元字符对于shell都有特殊含义,可分割单词,如果想使用其本身的含义就需要用到 ...