T1 夜莺与玫瑰

题目越发的变态起来。。。

这题刚开始看超级像仪仗队,好不容易码完欧拉函数后尝试×2后输出但不对!!

于是选择了跳过。。。。

正解居然是莫比乌斯函数。。。。我也是醉了

预处理完就剩下$O(1)$求解然而我做不到。。

于是打了超级恶心的前缀和$O(n^2)$预处理以及$O(Tn)$求解。

(多亏JYFHYX想到的手摸数组辗转相除超吊好吧)。

竟然还可以定义short数组防止MLE,小马长见识了。

先考虑到柿子:

$\sum_{a=1}^{n-1}\sum_{b-1}^{m-1}[gcd(a,b)==1]((n-a)(m-b)-max(n-2a,0)*max(m-2b,0))$

证明的话考虑原本筛到(a,b)点,

那么对于(1,1)到(a,b)的矩形每一个点以自己的a/b斜率向下划线作出的贡献是$(n-a)(m-b)$

然后向下再拓展出一个相同的矩形,

这个矩形与先前的那个矩形作出的贡献一样,则减去(前提保证斜率唯一特殊性,即gcd为1)

然后把括号拆开,发现一些不变的东西,

提取公因数之后发现可以维护三个前缀和(short开两个,剩下一个开int不会炸)

一个$prime_{i,j}$表示1~j中与i互质的数的个数(单为i那一层的)

一个$gcd_{i,j}$表示gcd为1的个数

一个$sum_{i,j}$表示1~j所有与i互质的数的和(单维护i那一层的)

然后通过化简的柿子算就行.

  1. 1 #include<bits/stdc++.h>
  2. 2 using namespace std;
  3. 3 inline int read(){
  4. 4 int x=0,f=1; char ch=getchar();
  5. 5 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
  6. 6 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
  7. 7 return x*f;
  8. 8 }
  9. 9 const int NN=4005,p=1073741824;
  10. 10 int T;
  11. 11 int sum[NN][NN];
  12. 12 short gcd[NN][NN],prime[NN][NN];
  13. 13 inline void pre(short n){
  14. 14 for(short i=1;i<=n;i++){
  15. 15 gcd[i][i]=gcd[i][0]=gcd[0][i]=i;
  16. 16 for(short j=1;j<i;j++)
  17. 17 gcd[i][j]=gcd[j][i]=gcd[j][i%j];
  18. 18 }
  19. 19 for(short i=1;i<=n;i++){
  20. 20 for(short j=1;j<=n;j++){
  21. 21 prime[i][j]=prime[i][j-1];
  22. 22 sum[i][j]=sum[i][j-1];
  23. 23 if(gcd[i][j]==1){
  24. 24 prime[i][j]++;
  25. 25 sum[i][j]+=j;
  26. 26 }
  27. 27 }
  28. 28 }
  29. 29 }
  30. 30 namespace WSN{
  31. 31 inline int main(){
  32. 32 pre(4000);
  33. 33 // FILE *A=freopen("1.in","r",stdin);
  34. 34 T=read();
  35. 35 while(T--){
  36. 36 short n=read(),m=read();
  37. 37 long long ans=0;
  38. 38 for(short i=1;i<n;i++){
  39. 39 (ans+=(n-i)*((long long)prime[i][m-1]*m%p-sum[i][m-1]+p))%=p;
  40. 40 if(2*i<n)
  41. 41 ((ans-=(long long)(n-2*i)*(prime[i][m/2]*m%p-2*sum[i][m/2]%p))+=p)%=p;
  42. 42 }
  43. 43 printf("%lld\n",(ans*2+n+m+p)%p);
  44. 44 }
  45. 45 return 0;
  46. 46 }
  47. 47 }
  48. 48 signed main(){return WSN::main();}

T2 影子

此题非常之离谱,不过$n^2$暴力超好打

正解是个并查集。

先跑树链剖分,把权值排序从大到小

遍历节点将其看作一个集合并将其与所有已经vis过的儿子merge出新的集合,

同时考虑六种情况,因为并查集维护了一个最长路,则有维护构成最长路的两个端点

分别考虑两个集合的不同端点连边构成最长(4种),原来的两个集合本身就有一个是新的最长(2种)

暴力枚举情况即可。最后用这个维护好的和遍历到的点权值相乘最小值即为答案。

  1. 1 #include<bits/stdc++.h>
  2. 2 #define int long long
  3. 3 using namespace std;
  4. 4 inline int read(){
  5. 5 int x=0,f=1; char ch=getchar();
  6. 6 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
  7. 7 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
  8. 8 return x*f;
  9. 9 }
  10. 10 const int NN=550000;
  11. 11 int T,n;
  12. 12 int son[NN],fa[NN],dep[NN],siz[NN],top[NN],dis[NN];
  13. 13 struct snow{int val,id;};snow d[NN];
  14. 14 inline bool cmp(snow a,snow b){return a.val>b.val;}
  15. 15 struct SNOW{int to,val,next;};SNOW e[NN]; int head[NN],rp;
  16. 16 struct node{int st,ed,len,fa;};node s[NN];
  17. 17 bool vis[NN];
  18. 18 inline void add(int x,int y,int z){e[++rp]=(SNOW){y,z,head[x]}; head[x]=rp;}
  19. 19 inline void dfs1(int f,int x){
  20. 20 dep[x]=dep[f]+1; siz[x]=1; fa[x]=f;
  21. 21 for(int i=head[x];i;i=e[i].next){
  22. 22 int y=e[i].to;
  23. 23 if(y==f) continue;
  24. 24 dis[y]=dis[x]+e[i].val;
  25. 25 dfs1(x,y);
  26. 26 siz[x]+=siz[y];
  27. 27 if(siz[son[x]]<siz[y]) son[x]=y;
  28. 28 }
  29. 29 }
  30. 30 inline void dfs2(int x,int t){
  31. 31 top[x]=t;
  32. 32 if(!son[x]) return; dfs2(son[x],t);
  33. 33 for(int i=head[x];i;i=e[i].next){
  34. 34 int y=e[i].to;
  35. 35 if(y!=fa[x]&&y!=son[x]) dfs2(y,y);
  36. 36 }
  37. 37 }
  38. 38 inline int LCA(int x,int y){
  39. 39 while(top[x]!=top[y]){
  40. 40 if(dep[top[x]]<dep[top[y]]) swap(x,y);
  41. 41 x=fa[top[x]];
  42. 42 }if(dep[x]>dep[y]) swap(x,y);
  43. 43 return x;
  44. 44 }
  45. 45 inline int getfa(int x){return s[x].fa==x?x:getfa(s[x].fa);}
  46. 46 inline void merge(int x,int y){
  47. 47 x=getfa(x),y=getfa(y); s[y].fa=x;
  48. 48 //不要直接定义新值,要不然会连不上边,merge后面的操作都是与fx,fy有关的!!!!!!!!!!!!!!!!!!!!!!
  49. 49 int stx=s[x].st,sty=s[y].st,edx=s[x].ed,edy=s[y].ed;
  50. 50 int dis1=dis[stx]+dis[sty]-2*dis[LCA(stx,sty)];
  51. 51 int dis2=dis[stx]+dis[edy]-2*dis[LCA(stx,edy)];
  52. 52 int dis3=dis[edx]+dis[sty]-2*dis[LCA(edx,sty)];
  53. 53 int dis4=dis[edx]+dis[edy]-2*dis[LCA(edx,edy)];
  54. 54 int dis5=s[y].len,dis6=s[x].len;
  55. 55 s[x].len=max(dis1,max(dis2,max(dis3,max(dis4,max(dis5,dis6)))));
  56. 56 // cout<<s[x].len<<endl;
  57. 57 if(s[x].len==dis1){s[x].ed=sty;return;}
  58. 58 if(s[x].len==dis2){s[x].ed=edy;return;}
  59. 59 if(s[x].len==dis3){s[x].st=sty;return;}
  60. 60 if(s[x].len==dis4){s[x].st=edy;return;}
  61. 61 if(s[x].len==dis5){s[x].st=sty; s[x].ed=edy;return;}
  62. 62 }
  63. 63 namespace WSN{
  64. 64 inline int main(){
  65. 65 // FILE *A=freopen("1.in","r",stdin);
  66. 66 // FILE *B=freopen("1.out","w",stdout);
  67. 67 T=read();
  68. 68 while(T--){
  69. 69 n=read();
  70. 70 int ans=0;
  71. 71 for(int i=1;i<=n;i++){
  72. 72 d[i].val=read();
  73. 73 d[i].id=i; s[i].fa=i;
  74. 74 }
  75. 75 for(int i=1;i<n;i++){
  76. 76 int u=read(),v=read(),w=read();
  77. 77 add(u,v,w); add(v,u,w);
  78. 78 }
  79. 79 dfs1(0,1); dfs2(1,1);
  80. 80 sort(d+1,d+n+1,cmp);
  81. 81 for(int i=1;i<=n;i++){
  82. 82 int nd=d[i].id,vv=d[i].val;
  83. 83 vis[nd]=1; s[nd].st=s[nd].ed=nd;
  84. 84 s[nd].len=0;
  85. 85 for(int j=head[nd];j;j=e[j].next){
  86. 86 int to=e[j].to;
  87. 87 if(vis[to]&&getfa(nd)!=getfa(to)) merge(nd,to);
  88. 88 }
  89. 89 ans=max(ans,vv*s[getfa(nd)].len);
  90. 90 }
  91. 91 printf("%lld\n",ans);
  92. 92 rp=0; for(int i=1;i<=n;i++) head[i]=0,dis[i]=0,son[i]=0,vis[i]=0;
  93. 93 memset(s,0,sizeof(s)); memset(d,0,sizeof(d));
  94. 94 }
  95. 95 return 0;
  96. 96 }
  97. 97 }
  98. 98 signed main(){return WSN::main();}

T3 玫瑰花精

看这题时给我的时间已经不多了,虽然看出跟hotel那题差不多但是没空阁哪里扣线段树了。

线段树中维护四个量。分别为在区间内最左,最右的花精位置,中间点,花精应放置的最优位置,

剩下的思路清晰,线段树板子一打。就剩下pushdown搁哪里空着啥也不会。。

考虑n种情况,其实先预先画个图,把维护的东西标识清楚情况自然出来了,剩下的代码也好理解。

  1. 1 void pushup(int id){
  2. 2 le[id]=le[lid]?le[lid]:le[rid];
  3. 3 ri[id]=ri[rid]?ri[rid]:ri[lid];
  4. 4 if(!le[lid]){mi[id]=mi[rid];po[id]=po[rid];return;}
  5. 5 if(!le[rid]){mi[id]=mi[lid];po[id]=po[lid];return;}
  6. 6 int cmo=(le[rid]-ri[lid])>>1;
  7. 7 int an=max(cmo,max(mi[lid],mi[rid]));
  8. 8 if(an==mi[lid]){mi[id]=mi[lid]; po[id]=po[lid];return;}
  9. 9 else if(an==cmo){mi[id]=cmo; po[id]=(le[rid]+ri[lid])>>1;return;}
  10. 10 else{mi[id]=mi[rid]; po[id]=po[rid];return;}
  11. 11 }

纤细的pushdown。。。

$fairy[x]$记录花精x的位置,注意输出时判断的三种情况。如果树是空树直接输出1。

  1. 1 #include<bits/stdc++.h>
  2. 2 #define lid (id<<1)
  3. 3 #define rid (id<<1|1)
  4. 4 using namespace std;
  5. 5 inline int min(int a,int b){return a<b?a:b;}
  6. 6 inline int max(int a,int b){return a>b?a:b;}
  7. 7 inline int read(){
  8. 8 int x=0,f=1; char ch=getchar();
  9. 9 while(ch<'0'||ch>'9'){ if(ch=='-') f=-1; ch=getchar(); }
  10. 10 while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
  11. 11 return x*f;
  12. 12 }
  13. 13 const int NN=3000000,inf=0x7fffffff;
  14. 14 int n,m,fairy[NN];
  15. 15 struct SNOWtree{
  16. 16 int ll[NN<<2],rr[NN<<2];
  17. 17 int le[NN<<2],ri[NN<<2],mi[NN<<2],po[NN<<2];
  18. 18 void pushup(int id){
  19. 19 le[id]=le[lid]?le[lid]:le[rid];
  20. 20 ri[id]=ri[rid]?ri[rid]:ri[lid];
  21. 21 if(!le[lid]){mi[id]=mi[rid];po[id]=po[rid];return;}
  22. 22 if(!le[rid]){mi[id]=mi[lid];po[id]=po[lid];return;}
  23. 23 int cmo=(le[rid]-ri[lid])>>1;
  24. 24 int an=max(cmo,max(mi[lid],mi[rid]));
  25. 25 if(an==mi[lid]){mi[id]=mi[lid]; po[id]=po[lid];return;}
  26. 26 else if(an==cmo){mi[id]=cmo; po[id]=(le[rid]+ri[lid])>>1;return;}
  27. 27 else{mi[id]=mi[rid]; po[id]=po[rid];return;}
  28. 28 }
  29. 29 void build(int id,int l,int r){
  30. 30 ll[id]=l; rr[id]=r;
  31. 31 if(l==r) return;
  32. 32 int mid=(l+r)>>1;
  33. 33 build(lid,l,mid); build(rid,mid+1,r);
  34. 34 }
  35. 35 void update(int id,int pos){
  36. 36 if(ll[id]==rr[id]){
  37. 37 le[id]=ri[id]=pos;
  38. 38 mi[id]=po[id]=0;
  39. 39 return;
  40. 40 }
  41. 41 int mid=(ll[id]+rr[id])>>1;
  42. 42 if(pos<=mid) update(lid,pos);
  43. 43 else update(rid,pos);
  44. 44 pushup(id);
  45. 45 }
  46. 46 void dele(int id,int pos){
  47. 47 if(ll[id]==rr[id]){
  48. 48 le[id]=ri[id]=mi[id]=po[id]=0;
  49. 49 return;
  50. 50 }
  51. 51 int mid=(ll[id]+rr[id])>>1;
  52. 52 if(pos<=mid) dele(lid,pos);
  53. 53 else dele(rid,pos);
  54. 54 pushup(id);
  55. 55 }
  56. 56 }tr;
  57. 57 namespace WSN{
  58. 58 inline int main(){
  59. 59 // FILE *A=freopen("1.in","r",stdin);
  60. 60 // FILE *B=freopen("1.out","w",stdout);
  61. 61 n=read();m=read();
  62. 62 tr.build(1,1,n);
  63. 63 for(int i=1;i<=m;i++){
  64. 64 int opt=read(),x=read();
  65. 65 if(opt==1){
  66. 66 // cout<<tr.le[1]-1<<" "<<tr.mi[1]<<" "<<n-tr.ri[1]<<endl;
  67. 67 // for(int j=1;j<=n*4;j++) if(tr.ll[j])
  68. 68 // cout<<tr.ll[j]<<" "<<tr.rr[j]<<" "<<tr.le[j]<<" "<<tr.ri[j]<<" "<<tr.mi[j]<<endl;
  69. 69 if(!tr.le[1]){
  70. 70 tr.update(1,1);
  71. 71 puts("1"); fairy[x]=1;
  72. 72 continue;
  73. 73 }
  74. 74 else{
  75. 75 int an=max(tr.le[1]-1,max(n-tr.ri[1],tr.mi[1]));
  76. 76 if(an==tr.le[1]-1){
  77. 77 puts("1");
  78. 78 fairy[x]=1;
  79. 79 tr.update(1,1);
  80. 80 continue;
  81. 81 }
  82. 82 else if(an==tr.mi[1]){
  83. 83 printf("%d\n",tr.po[1]);
  84. 84 fairy[x]=tr.po[1];
  85. 85 tr.update(1,tr.po[1]);
  86. 86 continue;
  87. 87 }
  88. 88 else{
  89. 89 printf("%d\n",n);
  90. 90 fairy[x]=n;
  91. 91 tr.update(1,n);
  92. 92 continue;
  93. 93 }
  94. 94 }
  95. 95 }
  96. 96 if(opt==2){
  97. 97 tr.dele(1,fairy[x]);
  98. 98 fairy[x]=0;
  99. 99 continue;
  100. 100 }
  101. 101 }
  102. 102 return 0;
  103. 103 }
  104. 104 }
  105. 105 signed main(){return WSN::main();}

Noip模拟15 2021.7.14的更多相关文章

  1. Noip模拟76 2021.10.14

    T1 洛希极限 上来一道大数据结构或者单调队列优化$dp$ 真就没分析出来正解复杂度 正解复杂度$O(q+nm)$,但是据说我的复杂度是假的 考虑一个点转移最优情况是从它上面的一个反$L$形转移过来 ...

  2. Noip模拟53 2021.9.14

    T1 ZYB和售货机 首先这道题有两种做法. 一种是发现每个点都可以先被取到只剩一个,只要收益大于$0$ 然后发现建一个$i->f[i]$的图时出现环,要把它去掉, 那么跑一个$tarjan$枚 ...

  3. Noip模拟39 2021.8.14

    T1 打地鼠 都切掉了的简单题 1 #include<bits/stdc++.h> 2 #define int long long 3 using namespace std; 4 con ...

  4. Noip模拟77 2021.10.15

    T1 最大或 $T1$因为没有开$1ll$右移给炸掉了,调了一年不知道为啥,最后实在不懂了 换成$pow$就过掉了,但是考场上这题耽误了太多时间,后面的题也就没办法好好打了.... 以后一定要注意右移 ...

  5. Noip模拟40 2021.8.15

    T1 送花 按照题解意思说是扫描线题,但我觉得像一个线段树优化$dp$ 主要思想一样,就是暴力枚举右端点,同时维护左端点的最值, 考虑两种情况, 如果左端点在$r$扫到的数$i$上一次出现的位置之前, ...

  6. Noip模拟16 2021.7.15

    题目真是越来越变态了 T1 Star Way To Heaven 首先,你要看出这是一个最小生成树的题(妙吧?) 为什么可以呢? 我们发现从两点连线的中点过是最优的,但是上下边界怎么办呢? 我们把上下 ...

  7. Noip模拟70 2021.10.6

    T1 暴雨 放在第一道的神仙题,不同的做法,吊人有的都在用线段树维护$set$预处理 我是直接$dp$的,可能代码的复杂度比那种的稍微小一点 设$f[i][j][p][0/1]$表示考虑了前$i$列, ...

  8. Noip模拟69 2021.10.5

    考场拼命$yy$高精度结果没学好$for$循环痛失$50pts$,当场枯死 以后一定打对拍,要不考后会... T1 石子游戏 首先要知道典型的$NIM$博弈,就是说如果所有堆石子个数的异或和为$0$则 ...

  9. Noip模拟63 2021.9.27(考场惊现无限之环)

    T1 电压机制 把题目转化为找那些边只被奇数环包含. 这样的话直接$dfs$生成一棵树,给每个点附上一个深度,根据其他的非树边都是返祖边 可以算出环内边的数量$dep[x]-dep[y]+1$,然后判 ...

随机推荐

  1. Linux的基础指令(二)

    目录:   一.列表显示目录内容-ls    二.设置别名-alias      三.统计目录及文件空间占用情况-du       四.创建新目录 -mkdir          五.创建空文件-to ...

  2. WPF 第三方资源

    1.XCeed 开发的Extended WPF Toolkit http://wpftoolkit.codeplex.com/ http://www.csdn123.com/html/blogs/20 ...

  3. python 打字小游戏

    最近随便用python的pygame编了这个打字小游戏 只要有字母调到窗口底部就结束 上代码: import pygame.freetype import sys import random pyga ...

  4. [Navicat15 试用期过期解决办法]

    Navicat15 试用期过期解决办法 第一步:关闭Navicat 第二步: 打开注册表编辑器,win + R, 输入regedit 第三步: 在最上方搜索框输入HKEY_CURRENT_USER\S ...

  5. 建立 F103C8T6 HAL库 Makefile FreeRTOS 工程

    F103C8T6 HAL库 Makefile FreeRTOS 工程模板 环境 该工程的开发平台为 ARM-GCC 工具链和 Make > arm-none-eabi-gcc -v gcc ve ...

  6. shell脚本中 /dev/null 的用途

    /dev/null 是一个特殊的设备文件,它丢弃一切写入其中的数据 可以将它 视为一个黑洞, 它等效于只写文件, 写入其中的所有内容都会消失, 尝试从中读取或输出不会有任何结果,同样,/dev/nul ...

  7. tomcat 跨域的配置

    * 允许所有跨域  E:\apache-tomcat-7.0.81\conf\web.xml  <filter> <filter-name>CorsFilter</fil ...

  8. 1.3redis小结--配置php reids拓展

    1.执行php文件 输出phpinfo();  <?php phpinfo(); 2.根据PHPinfo的信息确定需要下载的 php_redis.dll , php_igbinary.dll 版 ...

  9. IP多播与NAT地址转化

    IP多播 与单播相比,在一对多的通信中,多播可以大大减少网络资源.在互联网上进行多播就叫做IP多播,IP多播所传送的分组需要使用IP多播地址. 如果某台主机想要收到某个特定的多播分组,那么怎样才能是这 ...

  10. 深入理解Java虚拟机之JVM内存布局篇

    内存布局**** ​ JVM内存布局规定了Java在运行过程中内存申请.分配.管理的策略,保证了JVM的稳定高效运行.不同的JVM对于内存的划分方式和管理机制存在部分差异.结合JVM虚拟机规范,一起来 ...