「APIO 2019」奇怪装置

题目描述

有无限个二元组,每个二元组为\(((t+\left\lfloor\frac{t}{B} \right\rfloor)\%A,t \% B)\),给出一些区间,问他们之中有多少本质不同的二元组。

题解

考虑朴素做法,区间求并AC

考虑如果每个二元组为\((t\%A,t \% B)\)的话,那么它显然是有一个\(\frac{A*B}{(A,B)}\)的循环节的。

然后我们考虑所有在\(\%B\)意义下同余的所有数\(\%A\)意义下的结果。

他们形成了一个每节长度为\(B\)的一个环。

现在每个数又多了一个偏移量,相当于变成了\(B+1\)。

那么循环节就变成了\(\frac{A*B}{(A,B+1)}\)。

  1. #include<bits/stdc++.h>
  2. #define N 1000009
  3. using namespace std;
  4. typedef long long ll;
  5. ll n,A,B,ans;
  6. int tot;
  7. inline ll rd(){
  8. ll x=0;char c=getchar();bool f=0;
  9. while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  10. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
  11. return f?-x:x;
  12. }
  13. inline ll gcd(ll x,ll y){return y?gcd(y,x%y):x;}
  14. struct node{
  15. ll l,r;
  16. inline bool operator <(const node &b)const{
  17. return l<b.l;
  18. }
  19. }a[N<<1];
  20. int main(){
  21. n=rd();A=rd();B=rd();
  22. ll G=A/gcd(A,B+1)*B;
  23. if(G/B!=A/gcd(A,B+1))G=9e18;
  24. ll l,r;
  25. for(int i=1;i<=n;++i){
  26. l=rd();r=rd();
  27. if(r-l+1>=G){cout<<G;return 0;}
  28. l%=G;r%=G;
  29. if(l>r){
  30. a[++tot]=node{l,G-1};
  31. a[++tot]=node{0,r};
  32. }
  33. else a[++tot]=node{l,r};
  34. }
  35. sort(a+1,a+tot+1);
  36. ll p=0;
  37. for(int i=1;i<=tot;++i){
  38. p=max(p,a[i].l);
  39. ans+=max(0ll,a[i].r-p+1);
  40. p=max(p,a[i].r+1);
  41. }
  42. cout<<ans;
  43. return 0;
  44. }

「APIO 2019」桥梁

题目描述

无向图,边有边权,每次可以修改一条边的边权,或者询问从一个点出发走边权不小于w的边能够到达的点数。

题解

考虑朴素做法,定期重构AC

话说这不就是\([HNOI2016]\)最小公倍数吗?

然而那道题\(KD-tree\)分治能过,这题不行。

我们可以对所有操作分块,每个块内把边权不会动的边拿出来排序,会动的按照操作时间排序,每次用指针卡不会动的边,会动的暴力做就行了,做完一个快就就算所有修改。

代码

  1. #include<bits/stdc++.h>
  2. #define N 100002
  3. using namespace std;
  4. typedef long long ll;
  5. int n,m,n1,q;
  6. int top,top1,top2,top3,be[N],f[N],dep[N],ans[N];
  7. int size[N],pos[N];
  8. bool vis[N],vi[N];
  9. inline ll rd(){
  10. ll x=0;char c=getchar();bool f=0;
  11. while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  12. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
  13. return f?-x:x;
  14. }
  15. struct edge{
  16. int u,v,w,id;
  17. inline bool operator <(const edge &b)const{
  18. return w>b.w;
  19. }
  20. }b[N],st1[N];
  21. struct Q{
  22. int opt,u,v,id,tim;
  23. inline bool operator<(const Q &b)const{
  24. return v>b.v;
  25. }
  26. }c[N],st2[N],st3[N];
  27. struct node{
  28. int u,v,val;
  29. }st[N];
  30. int find(int x){return f[x]==x?x:find(f[x]);}
  31. inline void add(int u,int v,bool tag){
  32. int xx=find(u),yy=find(v);
  33. if(xx==yy)return;
  34. if(dep[xx]>dep[yy])swap(xx,yy);
  35. if(tag)st[++top]=node{xx,yy,dep[yy]};
  36. f[xx]=yy;size[yy]+=size[xx];dep[yy]=max(dep[yy],dep[xx]+1);
  37. }
  38. inline void del(){
  39. node x=st[top];top--;
  40. dep[x.v]=x.val;f[x.u]=x.u;size[x.v]-=size[x.u];
  41. }
  42. inline int query(int x){return size[find(x)];}
  43. int main(){
  44. n=rd();m=rd();
  45. int n1=max(20,(int)sqrt(max(1,m)*log2(n)));
  46. for(int i=1;i<=m;++i){
  47. b[i].u=rd();b[i].v=rd();b[i].w=rd();b[i].id=i;
  48. }
  49. sort(b+1,b+m+1);
  50. int dd=0;
  51. for(int i=1;i<=m;++i)pos[b[i].id]=i;
  52. q=rd();
  53. for(int i=1;i<=q;++i){
  54. c[i].opt=rd();c[i].u=rd();c[i].v=rd();
  55. c[i].tim=i;
  56. if(c[i].opt==2)c[i].id=++dd;
  57. }
  58. for(int i=1;i<=q;++i)be[i]=(i-1)/n1+1;
  59. for(int i=1;i<=be[q];++i){
  60. int l=(i-1)*n1+1,r=min(q,i*n1);
  61. top1=top2=top3=0;
  62. for(int j=l;j<=r;++j)
  63. if(c[j].opt==1)vi[c[j].u]=1,st3[++top3]=c[j];
  64. else st2[++top2]=c[j];
  65. sort(st2+1,st2+top2+1);
  66. for(int j=1;j<=n;++j)f[j]=j,size[j]=dep[j]=1;
  67. for(int j=1;j<=m;++j)if(!vi[b[j].id])st1[++top1]=b[j];
  68. int p=1;
  69. for(int j=1;j<=top2;++j){
  70. while(st1[p].w>=st2[j].v&&p<=top1)add(st1[p].u,st1[p].v,0),p++;
  71. for(int k=1;k<=top3;++k)if(st3[k].tim<st2[j].tim)vis[st3[k].u]=1;else break;
  72. for(int k=top3;k>=1;--k){
  73. if(st3[k].tim>st2[j].tim){
  74. if(!vis[st3[k].u]&&b[pos[st3[k].u]].w>=st2[j].v)add(b[pos[st3[k].u]].u,b[pos[st3[k].u]].v,1);
  75. continue;
  76. }
  77. if(vis[st3[k].u]&&st3[k].v>=st2[j].v)add(b[pos[st3[k].u]].u,b[pos[st3[k].u]].v,1);
  78. vis[st3[k].u]=0;
  79. }
  80. ans[st2[j].id]=query(st2[j].u);
  81. while(top)del();
  82. }
  83. for(int j=l;j<=r;++j){
  84. vi[c[j].u]=0;
  85. if(c[j].opt==1)b[pos[c[j].u]].w=c[j].v;
  86. }
  87. sort(b+1,b+m+1);
  88. for(int j=1;j<=m;++j)pos[b[j].id]=j;
  89. }
  90. for(int i=1;i<=dd;++i)printf("%d\n",ans[i]);
  91. return 0;
  92. }

「APIO 2019」路灯

题目描述

有一个序列,相邻两个元素之间有一个桥,每次改变一座桥的联通状态,或者询问两个点有多少时刻是联通的。

题解

考虑朴素做法,三维偏序AC

不过这个三维偏序确实比较明显,直接打个带时间戳的标记就行了。

代码

  1. #include<bits/stdc++.h>
  2. #define N 300009
  3. #define ls tr[cnt].l
  4. #define rs tr[cnt].r
  5. using namespace std;
  6. typedef long long ll;
  7. char S[N];
  8. bool nw[N];
  9. int tot,tott,nwtim,n,q,rot;
  10. set<int>s;
  11. set<int>::iterator it;
  12. inline ll rd(){
  13. ll x=0;char c=getchar();bool f=0;
  14. while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
  15. while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
  16. return f?-x:x;
  17. }
  18. int tag;
  19. struct point{
  20. int x[2];
  21. inline bool operator <(const point &b)const{
  22. if(x[tag]!=b.x[tag])return x[tag]<b.x[tag];
  23. else return x[tag^1]<b.x[tag^1];
  24. }
  25. inline bool operator ==(const point &b)const{
  26. return x[tag]==b.x[tag]&&x[tag^1]==b.x[tag^1];
  27. }
  28. }b[N];
  29. inline bool jiao(int l1,int r1,int l2,int r2){
  30. if(l1>l2)swap(l1,l2),swap(r1,r2);
  31. return (l2>=l1&&l2<=r1)||(r1>=l2&&r1<=r2);
  32. }
  33. inline bool In(int x,int l1,int r1){
  34. return x>=l1&&x<=r1;
  35. }
  36. struct matrix{
  37. point mi,mx;
  38. };
  39. struct seg{
  40. int l,r;
  41. point a,mx,mi;
  42. int la,sum;
  43. }tr[N];
  44. struct Q{
  45. int opt,x,y;
  46. }a[N];
  47. inline void pushdown(int cnt){
  48. if(ls)tr[ls].sum+=tr[cnt].la,tr[ls].la+=tr[cnt].la;
  49. if(rs)tr[rs].sum+=tr[cnt].la,tr[rs].la+=tr[cnt].la;
  50. tr[cnt].la=0;
  51. }
  52. inline void pushup(int cnt){
  53. tr[cnt].mi=tr[cnt].mx=tr[cnt].a;
  54. for(int i=0;i<2;++i){
  55. if(ls){
  56. tr[cnt].mi.x[i]=min(tr[cnt].mi.x[i],tr[ls].mi.x[i]);
  57. tr[cnt].mx.x[i]=max(tr[cnt].mx.x[i],tr[ls].mx.x[i]);
  58. }
  59. if(rs){
  60. tr[cnt].mi.x[i]=min(tr[cnt].mi.x[i],tr[rs].mi.x[i]);
  61. tr[cnt].mx.x[i]=max(tr[cnt].mx.x[i],tr[rs].mx.x[i]);
  62. }
  63. }
  64. }
  65. void build(int &cnt,int l,int r,int tg){
  66. if(l>r)return;
  67. if(!cnt)cnt=++tott;
  68. int mid=(l+r)>>1;
  69. tag=tg;
  70. nth_element(b+l,b+mid,b+r+1);
  71. tr[cnt].a=b[mid];
  72. build(ls,l,mid-1,tg^1);
  73. build(rs,mid+1,r,tg^1);
  74. pushup(cnt);
  75. }
  76. inline bool pd1(matrix x,seg now){
  77. if(x.mx.x[0]>=now.mx.x[0]&&x.mx.x[1]>=now.mx.x[1]&&x.mi.x[0]<=now.mi.x[0]&&x.mi.x[1]<=now.mi.x[1])
  78. return 1;
  79. return 0;
  80. }
  81. inline bool pd2(matrix x,seg now){
  82. if(pd1(x,now))return 1;
  83. if(!jiao(now.mi.x[0],now.mx.x[0],x.mi.x[0],x.mx.x[0]))return 0;
  84. if(!jiao(now.mi.x[1],now.mx.x[1],x.mi.x[1],x.mx.x[1]))return 0;
  85. return 1;
  86. }
  87. void upd(int cnt,matrix x,int y){
  88. if(pd1(x,tr[cnt])){
  89. tr[cnt].sum+=y;
  90. tr[cnt].la+=y;
  91. return;
  92. }
  93. if(In(tr[cnt].a.x[0],x.mi.x[0],x.mx.x[0])&&In(tr[cnt].a.x[1],x.mi.x[1],x.mx.x[1]))tr[cnt].sum+=y;
  94. if(ls&&pd2(x,tr[ls]))upd(ls,x,y);
  95. if(rs&&pd2(x,tr[rs]))upd(rs,x,y);
  96. }
  97. void query(int cnt,point x,int tg,int op){
  98. tag=tg;
  99. if(x==tr[cnt].a){
  100. printf("%d\n",tr[cnt].sum+nwtim*op);
  101. return;
  102. }
  103. pushdown(cnt);
  104. if(x<tr[cnt].a)query(ls,x,tg^1,op);
  105. else query(rs,x,tg^1,op);
  106. }
  107. void check(int cnt){
  108. printf("%d %d %d %d\n",cnt,tr[cnt].a.x[0],tr[cnt].a.x[1],tr[cnt].sum);
  109. pushdown(cnt);
  110. if(ls)check(ls);
  111. if(rs)check(rs);
  112. }
  113. int main(){
  114. n=rd()+1;q=rd();
  115. scanf("%s",S+1);
  116. for(int i=1;i<=n;++i)nw[i]=S[i]-'0';
  117. for(int i=1;i<=q;++i){
  118. scanf("%s",S);
  119. if(S[0]=='t'){a[i].opt=1;a[i].x=rd();}
  120. else {a[i].x=rd();a[i].y=rd();b[++tot]=point{a[i].x,a[i].y};}
  121. }
  122. sort(b+1,b+tot+1);
  123. tot=unique(b+1,b+tot+1)-b-1;
  124. build(rot,1,tot,0);
  125. matrix x;
  126. s.insert(0);s.insert(n);
  127. for(int i=1;i<n;++i)if(!nw[i])s.insert(i);
  128. for(int i=1;i<=q;++i){
  129. nwtim=i;
  130. if(a[i].opt){
  131. if(nw[a[i].x]){
  132. nw[a[i].x]=0;
  133. s.insert(a[i].x);
  134. it=s.lower_bound(a[i].x);
  135. --it;
  136. x.mi.x[0]=*it+1;x.mx.x[0]=a[i].x;
  137. ++it;++it;
  138. x.mi.x[1]=a[i].x+1;x.mx.x[1]=*it;
  139. upd(rot,x,nwtim);
  140. }
  141. else{
  142. nw[a[i].x]=1;
  143. it=s.lower_bound(a[i].x);
  144. --it;
  145. x.mi.x[0]=*it+1;x.mx.x[0]=a[i].x;
  146. ++it;++it;
  147. x.mi.x[1]=a[i].x+1;x.mx.x[1]=*it;
  148. upd(rot,x,-nwtim);
  149. --it;
  150. s.erase(it);
  151. }
  152. }
  153. else{
  154. it=s.lower_bound(a[i].x);
  155. if(*it<a[i].y)query(rot,point{a[i].x,a[i].y},0,0);
  156. else query(rot,point{a[i].x,a[i].y},0,1);
  157. }
  158. //check(rot);puts("");
  159. }
  160. return 0;
  161. }

APIO2019解题报告的更多相关文章

  1. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  2. 二模13day1解题报告

    二模13day1解题报告 T1.发射站(station) N个发射站,每个发射站有高度hi,发射信号强度vi,每个发射站的信号只会被左和右第一个比他高的收到.现在求收到信号最强的发射站. 我用了时间复 ...

  3. BZOJ 1051 最受欢迎的牛 解题报告

    题目直接摆在这里! 1051: [HAOI2006]受欢迎的牛 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4438  Solved: 2353[S ...

  4. 习题:codevs 2822 爱在心中 解题报告

    这次的解题报告是有关tarjan算法的一道思维量比较大的题目(真的是原创文章,希望管理员不要再把文章移出首页). 这道题蒟蒻以前做过,但是今天由于要复习tarjan算法,于是就看到codevs分类强联 ...

  5. 习题:codevs 1035 火车停留解题报告

    本蒟蒻又来写解题报告了.这次的题目是codevs 1035 火车停留. 题目大意就是给m个火车的到达时间.停留时间和车载货物的价值,车站有n个车道,而火车停留一次车站就会从车载货物价值中获得1%的利润 ...

  6. 习题: codevs 2492 上帝造题的七分钟2 解题报告

    这道题是受到大犇MagHSK的启发我才得以想出来的,蒟蒻觉得自己的代码跟MagHSK大犇的代码完全比不上,所以这里蒟蒻就套用了MagHSK大犇的代码(大家可以关注下我的博客,友情链接就是大犇MagHS ...

  7. 习题:codevs 1519 过路费 解题报告

    今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...

  8. NOIP2016提高组解题报告

    NOIP2016提高组解题报告 更正:NOIP day1 T2天天爱跑步 解题思路见代码. NOIP2016代码整合

  9. LeetCode 解题报告索引

    最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中......                        ...

随机推荐

  1. selenium:css_selector定位详解(css selector和xpath的比较)

    selenium使用css selector和xpath的比较 selenium提供的定位方式(常用) ID NAME CLASS CSS SELECTOR XPATH   推荐的定位方式的优先级 优 ...

  2. dotnet sdk 的镜像tag 相关

    https://hub.docker.com/_/microsoft-dotnet-core-sdk/ 微软的dotnet sdk 的 tag 微软貌似改默认镜像 dockerhub 里面的tag与 ...

  3. 【监控笔记】【1.1】监控事件系列——SQL Server Profiler

    声明:本系列是书目<sql server监控与诊断读书笔记> 联机丛书监控:https://docs.microsoft.com/en-us/sql/relational-database ...

  4. [Bzoj1597][Usaco2008 Mar]土地购买(斜率优化)

    题目链接 因为题目说可以分组,并且是求最值,所以斜率优化应该是可以搞的,现在要想怎么排序使得相邻的数在一个组中最优. 我们按照宽$w$从小到大,高$h$从小到大排序.这时发现可以筛掉一些一定没有贡献的 ...

  5. pistat 查看进程状态

    该pidstat命令用于监视当前正在由Linux内核管理的各个任务.对于使用选项-p选择的每个任务,或者如果使用了选项-p ALL,则它将写入Linux内核管理的 每个任务的标准输出活动.不选择任何任 ...

  6. 迁移数据库mysql

    文档 <http://site.clairvoyantsoft.com/migrate-cloudera-scm-database-from-postgresql-to-mysql/> h ...

  7. Linux命令(持续更新)

    1. tail 命令    tail 命令可用于查看文件的内容,有一个常用的参数 -f 常用于查阅正在改变的日志文件. tail  -f  filename 会把 filename 文件里的最尾部的内 ...

  8. WNMP环境搭建步骤 nginx1.4.3+php-5.3.27+mysql-5.5+RunHiddenConsole

    安装目录:D:/webServer/所需软件:     mysql-installer-community-5.5.34.0.msi         下载:http://cdn.mysql.com/D ...

  9. luogu P1398 [NOI2013]书法家

    传送门 注意到\(N\ O\ I\)三个字母都可以从左到右拆成三部分,即\(N=\)一个矩形+一堆矩形+一个矩形,\(O=\)一条+两条横的+一条,\(I=\)两条横的+一个矩形+两条横的,所以可以拆 ...

  10. 前端为什么要学习 Selenium

    如果你正在阅读本文,那么可能希望从手动测试升级为自动化测试.你是对的,因为你需要学习 Selenium.我这样说是因为自动化测试已经风靡全球,而且业界正很缺少 Selenium 认证专家. 你可能还想 ...