2015-2016 Petrozavodsk Winter Training Camp, Nizhny Novgorod SU Contest

B. Forcefield

题意

给你一维平面上n个镜子,镜子的朝向有正面和背面,如果光束从正面穿过,会摧毁镜子,并且光束会反向;如果从背面穿过的话,什么都不会发生。

光束一开始从X位置,射向0点,然后你人在0点,会反射光束。

问你要破坏所有镜子,人需要反弹光束多少次。

数据范围100000

题解

其实模拟就好了,击破镜子的顺序就那么一种。

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 1e5+6;
  4. const int inf = 1e9+1;
  5. set<int> s1,s2;
  6. int n,x[maxn],p[maxn];
  7. set<int>::iterator it;
  8. int main()
  9. {
  10. scanf("%d%d",&n,&x[0]);
  11. for(int i=1;i<=n;i++)
  12. {
  13. scanf("%d%d",&x[i],&p[i]);
  14. if(p[i]==1)s1.insert(x[i]);
  15. if(p[i]==0)s2.insert(x[i]);
  16. }
  17. s2.insert(0);
  18. s1.insert(0);
  19. s2.insert(inf);
  20. s1.insert(inf);
  21. int now = x[0],flag=2;
  22. int ans = 0;
  23. while(1)
  24. {
  25. if(flag==2){
  26. int pos = *--s2.lower_bound(now);
  27. if(pos==0){
  28. ans++;
  29. now=pos;
  30. }
  31. else{
  32. s2.erase(pos);
  33. now=pos;
  34. }
  35. flag=1;
  36. }else{
  37. int pos = *s1.upper_bound(now);
  38. if(pos==inf){
  39. if(s1.size()==2&&s2.size()==2)
  40. break;
  41. printf("-1\n");
  42. return 0;
  43. }else{
  44. s1.erase(pos);
  45. now=pos;
  46. }
  47. flag=2;
  48. }
  49. }
  50. cout<<ans<<endl;
  51. }

C.Missing Part

题意

给你一个串S,这个S是环状的,给你另外一个字符串S1。

给你大写的ABCDE和小写的abcde,然后你需要定义一种对应关系,使得失配数最小。

题解

假设只有两种字符,那么就是FFT了。

然后这个是5个嘛,最粗鲁的做法是120个FFT。

优化一下 就是25个FFT就好了。

队友写的,实验细节不知道。

代码

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 5e4 + 50;
  4. char s1[maxn << 1],s2[maxn];
  5. int n ,ans,f[15],use[15];
  6. vector < int > pos[5] , ano[5];
  7. const double PI = acos(-1.0);
  8. //复数结构体
  9. struct Complex
  10. {
  11. double r,i;
  12. Complex(double _r = 0.0,double _i = 0.0)
  13. {
  14. r = _r; i = _i;
  15. }
  16. Complex operator +(const Complex &b)
  17. {
  18. return Complex(r+b.r,i+b.i);
  19. }
  20. Complex operator -(const Complex &b)
  21. {
  22. return Complex(r-b.r,i-b.i);
  23. }
  24. Complex operator *(const Complex &b)
  25. {
  26. return Complex(r*b.r-i*b.i,r*b.i+i*b.r);
  27. }
  28. };
  29. /*
  30. * 进行FFT和IFFT前的反转变换。
  31. * 位置i和 (i二进制反转后位置)互换
  32. * len必须去2的幂
  33. */
  34. void change(Complex y[],int len)
  35. {
  36. int i,j,k;
  37. for(i = 1, j = len/2;i < len-1; i++)
  38. {
  39. if(i < j)swap(y[i],y[j]);
  40. //交换互为小标反转的元素,i<j保证交换一次
  41. //i做正常的+1,j左反转类型的+1,始终保持i和j是反转的
  42. k = len/2;
  43. while( j >= k)
  44. {
  45. j -= k;
  46. k /= 2;
  47. }
  48. if(j < k) j += k;
  49. }
  50. }
  51. /*
  52. * 做FFT
  53. * len必须为2^k形式,
  54. * on==1时是DFT,on==-1时是IDFT
  55. */
  56. void fft(Complex y[],int len,int on)
  57. {
  58. change(y,len);
  59. for(int h = 2; h <= len; h <<= 1)
  60. {
  61. Complex wn(cos(-on*2*PI/h),sin(-on*2*PI/h));
  62. for(int j = 0;j < len;j+=h)
  63. {
  64. Complex w(1,0);
  65. for(int k = j;k < j+h/2;k++)
  66. {
  67. Complex u = y[k];
  68. Complex t = w*y[k+h/2];
  69. y[k] = u+t;
  70. y[k+h/2] = u-t;
  71. w = w*wn;
  72. }
  73. }
  74. }
  75. if(on == -1)
  76. for(int i = 0;i < len;i++)
  77. y[i].r /= len;
  78. }
  79. int len = 131072;
  80. Complex X[131075],Y[131075];
  81. int ret[5][5][maxn];
  82. void predeal(){
  83. for(int i = 0 ; i < 5 ; ++ i)
  84. for(int j = 0 ; j < 5 ; ++ j){
  85. memset( X , 0 , sizeof( X ) );
  86. memset( Y , 0 , sizeof( Y ) );
  87. int x = i , y = j;
  88. for(auto it : pos[i]) X[it+1].r++;
  89. for(auto it : ano[y]) Y[n-it].r++;
  90. fft( X , len , 1 );
  91. fft( Y , len , 1 );
  92. for(int j = 0 ; j < len ; ++ j) X[j] = X[j] * Y[j];
  93. fft( X , len , -1 );
  94. for(int k = n + 1 ; k <= 2 * n ; ++ k) ret[i][j][k - n] += (int)(X[k].r + 0.5);
  95. }
  96. }
  97. void cal_ans(){
  98. for(int i = 1 ; i <= n ; ++ i){
  99. int sum = 0;
  100. for(int j = 0 ; j < 5 ; ++ j)
  101. sum += ret[j][f[j]][i];
  102. ans = max( ans , sum );
  103. }
  104. }
  105. void DFS( int x ){
  106. if( x == 5 ){
  107. cal_ans();
  108. }else{
  109. for(int i = 0 ; i < 5 ; ++ i)
  110. if(!use[i]){
  111. f[x] = i;
  112. use[i] = 1;
  113. DFS( x + 1 );
  114. use[i] = 0;
  115. }
  116. }
  117. }
  118. int main(int argc , char * argv[] ){
  119. freopen("in.txt","r",stdin);
  120. scanf("%s%s",s1,s2);
  121. n=strlen(s1);
  122. for(int i = 0 ; i < n ; ++ i) s1[i + n] = s1[i];
  123. for(int i = 0 ; i < (n * 2) ; ++ i) pos[s1[i] - 'A'].push_back( i );
  124. for(int i = 0 ; i < n ; ++ i) ano[s2[i] - 'a'].push_back( i );
  125. predeal();
  126. DFS( 0 );
  127. printf("%d\n",n-ans);
  128. return 0;
  129. }

The Jedi Killer

题意

平面上给你三个点,然后给你三条线段的长度,两条为lg,一条为lm。

三条线段的一个端点都在同一个位置,且lg垂直于lm。

问你这三个线段是否能够覆盖题目所给的三个点。

题解

丝薄题,XJB判一判就好了。

就三种情况,lm穿过两个点,lg穿过两个点,或者三点共线。

判判判就好了。

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. struct point
  4. {
  5. long long x,y;
  6. }p[3];
  7. long long cross(point p1,point p2,point p0)
  8. {
  9. return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
  10. }
  11. long long dist2(point p1,point p2)
  12. {
  13. return (p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y);
  14. }
  15. void solve()
  16. {
  17. long long lg,lm;
  18. cin>>lm>>lg;
  19. for(int i=0;i<3;i++)
  20. cin>>p[i].x>>p[i].y;
  21. if(cross(p[0],p[1],p[2])==0)
  22. {
  23. long long tmp=max(lm*lm,lg*lg*4LL);
  24. if(dist2(p[0],p[1])<=tmp&&dist2(p[1],p[2])<=tmp&&dist2(p[2],p[0])<=tmp)
  25. printf("YES\n");
  26. else
  27. printf("NO\n");
  28. return ;
  29. }
  30. for(int i=0;i<3;i++)
  31. {
  32. for(int j=i+1;j<3;j++)
  33. {
  34. for(int k=0;k<3;k++)
  35. if(k!=i&&k!=j)
  36. {
  37. int flag=1;
  38. long long a=p[i].y-p[j].y,b=p[j].x-p[i].x;
  39. long long c=-a*p[i].x-b*p[i].y;
  40. long long tmp=(a*p[k].x+b*p[k].y+c)*(a*p[k].x+b*p[k].y+c);
  41. if(lm*lm*(a*a+b*b)<tmp) flag=0;
  42. if(dist2(p[i],p[k])*(a*a+b*b)-tmp>lg*lg*(a*a+b*b)) flag=0;
  43. if(dist2(p[j],p[k])*(a*a+b*b)-tmp>lg*lg*(a*a+b*b)) flag=0;
  44. if(flag)
  45. {
  46. printf("YES\n");
  47. return ;
  48. }
  49. flag=1;
  50. if((dist2(p[i],p[j])+dist2(p[i],p[k])-dist2(p[j],p[k]))>0&&(dist2(p[i],p[j])+dist2(p[j],p[k])-dist2(p[i],p[k]))>0) flag=0;
  51. if(lg*lg*(a*a+b*b)<tmp) flag=0;
  52. if(dist2(p[i],p[k])*(a*a+b*b)-tmp>lm*lm*(a*a+b*b)) flag=0;
  53. if(dist2(p[j],p[k])*(a*a+b*b)-tmp>lm*lm*(a*a+b*b)) flag=0;
  54. if(flag)
  55. {
  56. printf("YES\n");
  57. return ;
  58. }
  59. }
  60. }
  61. }
  62. printf("NO\n");
  63. }
  64. int main()
  65. {
  66. int t;
  67. scanf("%d",&t);
  68. while(t--)solve();
  69. return 0;
  70. }

G. Youngling Tournament

题意

给你n个数,然后从大到小排序,如果这个数不小于他后面的数的和,那么这个数就是胜利者。

单点修改,问你每次胜利者有多少个。

题解

其实就是问你f[i]+sum[i]>=sum[n]的有多少个。

实际上就是区间修改+单点修改+查询区间第k大。

分块莽莽莽,然后再调一调常数就好了。

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn = 2e5+7;
  4. inline long long read()
  5. {
  6. long long x=0,f=1;char ch=getchar();
  7. while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
  8. while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
  9. return x*f;
  10. }
  11. int n,N,m,num,belong[maxn],x[maxn],block,l[maxn],r[maxn],flag[maxn],p[maxn];
  12. long long a[maxn],val[maxn],c[maxn];
  13. long long sum[maxn],B[2000];
  14. long long d[maxn];
  15. map<long long,int> H;
  16. int use[maxn],cnt;
  17. vector<int>E[maxn];
  18. int getid(long long x)
  19. {
  20. if(H[x])return H[x];
  21. if(!H[x])H[x]=++cnt;
  22. return H[x];
  23. }
  24. vector<long long> V;
  25. void build()
  26. {
  27. N=V.size();
  28. block=sqrt(N/2);
  29. num=N/block;if(N%block)num++;
  30. for(int i=1;i<=num;i++)
  31. l[i]=(i-1)*block+1,r[i]=i*block;
  32. r[num]=N;
  33. for(int i=1;i<=N;i++)
  34. belong[i]=(i-1)/block+1;
  35. int tot = 1;
  36. for(int i=1;i<=N;i++)
  37. E[getid(a[i])].push_back(i);
  38. for(int i=1;i<=n;i++)
  39. flag[E[getid(c[i])][use[getid(c[i])]++]]=1;
  40. }
  41. void build(int l,int r)
  42. {
  43. int id=belong[l];B[id]=0;
  44. for(int i=l;i<=r;i++)d[i]=0,sum[i]=0;
  45. for(int i=l;i<=r;i++)
  46. {
  47. if(i!=l)sum[i]=sum[i-1];
  48. if(flag[i]==1){
  49. sum[i]+=a[i];
  50. B[id]+=a[i];
  51. d[i]=a[i]+sum[i];
  52. }else{
  53. d[i]=-1e9;
  54. }
  55. }
  56. sort(d+l,d+r+1);
  57. }
  58. void query()
  59. {
  60. long long Sum = 0;
  61. for(int i=1;i<=num;i++)
  62. Sum+=B[i];
  63. long long tmp = 0;
  64. int ans = 0;
  65. for(int i=1;i<=num;i++)
  66. {
  67. int L=l[i],R=r[i],Ans=r[i]+1;
  68. while(L<=R)
  69. {
  70. int mid=(L+R)/2;
  71. if(d[mid]+tmp>=Sum)Ans=mid,R=mid-1;
  72. else L=mid+1;
  73. }
  74. ans+=(r[i]-Ans+1);
  75. tmp+=B[i];
  76. }
  77. printf("%d\n",ans);
  78. }
  79. int main()
  80. {
  81. //freopen("1.in","r",stdin);
  82. scanf("%d",&n);
  83. for(int i=1;i<=n;i++)
  84. {
  85. a[i]=read();c[i]=a[i];
  86. V.push_back(a[i]);
  87. }
  88. scanf("%d",&m);
  89. for(int i=1;i<=m;i++)
  90. {
  91. p[i]=read();val[i]=read();
  92. V.push_back(val[i]);
  93. }
  94. sort(V.begin(),V.end());
  95. reverse(V.begin(),V.end());
  96. for(int i=0;i<V.size();i++)
  97. a[i+1]=V[i];
  98. build();
  99. for(int i=1;i<=num;i++)
  100. build(l[i],r[i]);
  101. query();
  102. for(int i=1;i<=m;i++)
  103. {
  104. int pos = E[getid(c[p[i]])][--use[getid(c[p[i]])]];
  105. flag[pos]=0;
  106. build(l[belong[pos]],r[belong[pos]]);
  107. c[p[i]]=val[i];
  108. pos=E[getid(c[p[i]])][use[getid(c[p[i]])]++];
  109. flag[pos]=1;
  110. build(l[belong[pos]],r[belong[pos]]);
  111. query();
  112. }
  113. }

H. Garland Checking

题意

强制在线,给你一棵树

三个操作:

连接a,b

切掉a,b

查询a,b之间是否有边。

题解

裸LCT

代码

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int MAXN = 200010;
  4. struct Node {
  5. Node *ch[2], *p; int size, value;
  6. bool rev;
  7. Node(int t = 0);
  8. inline bool dir(void) {return p->ch[1] == this;}
  9. inline void SetC(Node *x, bool d) {
  10. ch[d] = x; x->p = this;
  11. }
  12. inline void Rev(void) {
  13. swap(ch[0], ch[1]); rev ^= 1;
  14. }
  15. inline void Push(void) {
  16. if (rev) {
  17. ch[0]->Rev();
  18. ch[1]->Rev();
  19. rev = 0;
  20. }
  21. }
  22. inline void Update(void) {
  23. size = ch[0]->size + ch[1]->size + 1;
  24. }
  25. }Tnull, *null = &Tnull, *fim[MAXN];
  26. // 要记得额外更新null的信息
  27. Node::Node(int _value){ch[0] = ch[1] = p = null; rev = 0;}
  28. inline bool isRoot(Node *x) {return x->p == null || (x != x->p->ch[0] && x != x->p->ch[1]);}
  29. inline void rotate(Node *x) {
  30. Node *p = x->p; bool d = x->dir();
  31. p->Push(); x->Push();
  32. if (!isRoot(p)) p->p->SetC(x, p->dir()); else x->p = p->p;
  33. p->SetC(x->ch[!d], d);
  34. x->SetC(p, !d);
  35. p->Update();
  36. }
  37. inline void splay(Node *x) {
  38. x->Push();
  39. while (!isRoot(x)) {
  40. if (isRoot(x->p)) rotate(x);
  41. else {
  42. if (x->dir() == x->p->dir()) {rotate(x->p); rotate(x);}
  43. else {rotate(x); rotate(x);}
  44. }
  45. }
  46. x->Update();
  47. }
  48. inline Node* Access(Node *x) {
  49. Node *t = x, *q = null;
  50. for (; x != null; x = x->p) {
  51. splay(x); x->ch[1] = q; q = x;
  52. }
  53. splay(t); //info will be updated in the splay;
  54. return q;
  55. }
  56. inline void Evert(Node *x) {
  57. Access(x); x->Rev();
  58. }
  59. inline void link(Node *x, Node *y) {
  60. Evert(x); x->p = y;
  61. }
  62. inline Node* getRoot(Node *x) {
  63. Node *tmp = x;
  64. Access(x);
  65. while (tmp->Push(), tmp->ch[0] != null) tmp = tmp->ch[0];
  66. splay(tmp);
  67. return tmp;
  68. }
  69. // 一定要确定x和y之间有边
  70. inline void cut(Node *x, Node *y) {
  71. Access(x); splay(y);
  72. if (y->p != x) swap(x, y);
  73. Access(x); splay(y);
  74. y->p = null;
  75. }
  76. inline Node* getPath(Node *x, Node *y) {
  77. Evert(x); Access(y);
  78. return y;
  79. }
  80. inline void clear(void) {
  81. null->rev = 0; null->size = 0; null->value = 0;
  82. }
  83. int judge(Node *x,Node *y)
  84. {
  85. while(x->p!=null)x = x->p;
  86. while(y->p!=null)y = y->p;
  87. if(x!=y)return 0;
  88. return 1;
  89. }
  90. int main()
  91. {
  92. clear();
  93. int n;
  94. cin>>n;
  95. for(int i=1;i<=n;i++)
  96. fim[i] = new Node();
  97. string c;
  98. int u,v;
  99. while(1)
  100. {
  101. cin>>c;
  102. if(c[0]=='E')break;
  103. cin>>u>>v;
  104. if(c[0]=='T')
  105. {
  106. if(judge(fim[u],fim[v]))
  107. cout<<"YES"<<endl;
  108. else
  109. cout<<"NO"<<endl;
  110. }
  111. else if(c[0]=='C')
  112. link(fim[u],fim[v]);
  113. else
  114. cut(fim[u],fim[v]);
  115. }
  116. }

2015-2016 Petrozavodsk Winter Training Camp, Nizhny Novgorod SU Contest (5/9)的更多相关文章

  1. 2015 UESTC Winter Training #7【2010-2011 Petrozavodsk Winter Training Camp, Saratov State U Contest】

    2015 UESTC Winter Training #7 2010-2011 Petrozavodsk Winter Training Camp, Saratov State U Contest 据 ...

  2. Petrozavodsk Winter Training Camp 2018 Jagiellonian U Contest Problem A. XOR

    先把所有的数异或起来 得到sum 然后sum有一些位是1一些位是0 是0的位表示所有数里面有这位的数是偶数个 则无论怎么划分数 这一位对最终的答案都是不会有贡献的  因为偶数=偶数+偶数/奇数+奇数 ...

  3. Petrozavodsk Winter Training Camp 2018

    Petrozavodsk Winter Training Camp 2018 Problem A. Mines 题目描述:有\(n\)个炸弹放在\(x\)轴上,第\(i\)个位置为\(p_i\),爆炸 ...

  4. 2014-2015 Petrozavodsk Winter Training Camp, Contest.58 (Makoto rng_58 Soejima contest)

    2014-2015 Petrozavodsk Winter Training Camp, Contest.58 (Makoto rng_58 Soejima contest) Problem A. M ...

  5. Petrozavodsk Winter Training Camp 2016: Moscow SU Trinity Contest

    题目列表 A.ABBA E.Elvis Presley G. Biological Software Utilities J. Burnished Security Updates A.ABBA 题意 ...

  6. 【推导】【数学期望】【冒泡排序】Petrozavodsk Winter Training Camp 2018 Day 5: Grand Prix of Korea, Sunday, February 4, 2018 Problem C. Earthquake

    题意:两地之间有n条不相交路径,第i条路径由a[i]座桥组成,每座桥有一个损坏概率,让你确定一个对所有桥的检测顺序,使得检测所需的总期望次数最小. 首先,显然检测的时候,是一条路径一条路径地检测,跳跃 ...

  7. 【线段树】【扫描线】Petrozavodsk Winter Training Camp 2018 Day 5: Grand Prix of Korea, Sunday, February 4, 2018 Problem A. Donut

    题意:平面上n个点,每个点带有一个或正或负的权值,让你在平面上放一个内边长为2l,外边长为2r的正方形框,问你最大能圈出来的权值和是多少? 容易推出,能框到每个点的 框中心 的范围也是一个以该点为中心 ...

  8. 【取对数】【哈希】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem J. Bobby Tables

    题意:给你一个大整数X的素因子分解形式,每个因子不超过m.问你能否找到两个数n,k,k<=n<=m,使得C(n,k)=X. 不妨取对数,把乘法转换成加法.枚举n,然后去找最大的k(< ...

  9. 【BFS】【最小生成树】Petrozavodsk Winter Training Camp 2018 Day 1: Jagiellonian U Contest, Tuesday, January 30, 2018 Problem G. We Need More Managers!

    题意:给你n个点,点带权,任意两点之间的边权是它们的点权的异或值中“1”的个数,问你该图的最小生成树. 看似是个完全图,实际上有很多边是废的.类似……卡诺图的思想?从读入的点出发BFS,每次只到改变它 ...

随机推荐

  1. 网络_OSI模型_数据包传输

    2017年1月12日, 星期四 网络_OSI模型_数据包传输 1.  网络_源主机_局域网_交换机_路由器_目标主机 2. OSI7七层_TCP/IP精简 OSI 7层:       应用层     ...

  2. 读asyncio模块源码时的知识补漏

    硬着头皮看了一周的asyncio模块代码,了解了大概的执行流程,引用太多,成尤其是对象间函数的引用. 光是这么一段简单的代码: # coding: utf8 import asyncio import ...

  3. .NET面试题系列(三)排序算法

    冒泡排序 , , , , , 7, 2, 4 }; //外层循环控制排序趟数 ; i < arr.Length - ; i++) { //内层循环控制每一趟排序多少次 ; j < arr. ...

  4. Hibernate的实体规则、主键生成策略、对象状态

    一. hibernate的实体类有一定的规则,类似于mybatis的逆向工程导出的实体类.具体的规则以及原因如下: 1.持久化类需要提供无参的构造方法. 因为hibernate底层采用反射机制创建对象 ...

  5. 修改history记录数门限

    你的 Bash 命令历史保存的历史命令的数量可以在 ~/.bashrc 文件里设置.在这个文件里,你可以找到下面两行: HISTSIZE=1000 HISTFILESIZE=2000 HISTSIZE ...

  6. C语言清空输入缓冲区的N种方法对比【转】

    转自:http://www.cnblogs.com/codingmylife/archive/2010/04/18/1714954.html C语言中有几个基本输入函数: //获取字符系列 int f ...

  7. Python3安装配置【转】

    不建议卸载python2 可能会导致系统内其他软件无法使用,如果使用最新的Python3那么我们知道编译安装源码包和系统默认包之间是没有任何影响的,所以可以安装python3和python2共存 (前 ...

  8. 用一句SQL查询相对复杂的统计报表

    --统计从2017年3月份开始每个月金融服务支付前分期申请数以及通过(核账完成)数 ,ApplyTime)) ,ApplyTime)) as varchar)+'月' as 日期,count(*) a ...

  9. FFT(快速傅里叶变换)摘要

    怎么说呢...这次的代码码风有点... 从这篇博客开始,我终于会用LATEX了!撒花 注:以下涉及多项式的n均表示多项式的次数 FFT用途 很简单,多项式相乘. FFT原理 如果暴力乘,复杂度是$O( ...

  10. Java实现继承过程概述

    super(); 在调用子类的构造器的时候,如果没有显示的写出 super(); ,那么,编译器会在佛那个加上 super(); 无参构造器 如果想调用父类的有参构造器,那么,必须显示的调用,编译器不 ...