前言

CSP之后第一次模拟赛,感觉考的一般。

不得不吐槽多校联测 OJ 上的评测机是真的慢。。。

T1 树上的数

解题思路

感觉自己思维有些固化了,一看题目就感觉是线段树。

考完之后才想起来这玩意直接 DFS 一遍就行(大雾

然后就是卡常了,最后的结果就是时限 2s 的题本机 0.6s 才在OJ上过掉,我谔谔

果然迭代比递归快,所以直接 BFS 就可以减小常数了QAQ

code

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define ull unsigned long long
  4. #define f() cout<<"RP++"<<endl
  5. using namespace std;
  6. inline int read()
  7. {
  8. int x=0,f=1; char ch=getchar();
  9. while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  10. while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  11. return x*f;
  12. }
  13. const int N=5e6+10,base=19760817;
  14. int n,m,A,B,X,Y,q,cnt,hd,tail,que[N];
  15. int tot=1,head[N],ver[N],nxt[N];
  16. bool vis[N];
  17. ll ans;
  18. inline void add_edge(int x,int y)
  19. {
  20. ver[++tot]=y;
  21. nxt[tot]=head[x];
  22. head[x]=tot;
  23. }
  24. int main()
  25. {
  26. freopen("tree.in","r",stdin); freopen("tree.out","w",stdout);
  27. cnt=n=read(); m=read(); A=read(); B=read(); add_edge(1,2);
  28. for(int i=3,temp=1;i<=n;i++) temp=((1ll*temp*A+B)^base)%(i-1)+1,add_edge(temp,i);
  29. q=read(); X=read(); Y=read();
  30. for(int i=1;i<=m;i++)
  31. {
  32. if(i!=1) q=(((1ll*q*X+Y)^base)^(i<<1))%(n-1)+2;
  33. hd=1;tail=0;if(!vis[q]) que[++tail]=q;
  34. while(hd<=tail)
  35. {
  36. int x=que[hd++]; vis[x]=true; cnt--;
  37. for(int j=head[x];j;j=nxt[j])
  38. if(!vis[ver[j]]) que[++tail]=ver[j];
  39. }
  40. ans^=cnt;
  41. }
  42. printf("%lld",ans);
  43. return 0;
  44. }

T2 时代的眼泪

解题思路

大概有一点换根 DP 的思想吧,但是还是卡常,吐了。

比较直接的思路就是先计算出以 1 为根的答案,然后求出每个点相对于父亲节点变化的答案。

主席树和线段树合并的复杂度都是对的,但是都会被卡常!!!

因此需要树状数组,我们需要的无非就是一个全局的,一个以某棵子树为根的答案嘛。。

对于全局总体的直接一个桶+前缀和,然后对于某颗子树的就可以用搜索子树之前的信息减去搜索子树之后的信息,这样就可以用上小常数的树状数组了。。

实测差距还是很大的,以后还是要注意常数问题啊。。

code

被卡成 90pts 的线段树合并

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define ull unsigned long long
  4. #define f() cout<<"RP++"<<endl
  5. #define ls tre[x].l
  6. #define rs tre[x].r
  7. using namespace std;
  8. inline int read()
  9. {
  10. int x=0,f=1;char ch=getchar();
  11. while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  12. while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  13. return x*f;
  14. }
  15. inline void write(int x)
  16. {
  17. return printf("%lld",x),void();
  18. #define sta number
  19. int sta[70],top=0; if(x<0) putchar('-'),x=~(x-1);
  20. while(x) sta[++top]=x%10,x/=10; if(!top) sta[++top]=0;
  21. while(top) putchar(sta[top--]+'0');
  22. #undef sta
  23. }
  24. const int N=1e6+10;
  25. int n,m,lim,all,cnt,root[N],s[N],fa[N];
  26. int tot=1,head[N],ver[N<<1],nxt[N<<1];
  27. struct Node{ll dat;int l,r;}tre[N*30];
  28. vector<int> sta;
  29. ll ans[N];
  30. void add_edge(int x,int y)
  31. {
  32. ver[++tot]=y;
  33. nxt[tot]=head[x];
  34. head[x]=tot;
  35. }
  36. int New()
  37. {
  38. if(!sta.size()) return ++all;
  39. int x=sta[sta.size()-1];
  40. tre[x].dat=ls=rs=0;
  41. return sta.pop_back(),x;
  42. }
  43. #define push_up(x) tre[x].dat=tre[ls].dat+tre[rs].dat;
  44. inline void insert(int &x,int l,int r,int pos,int val)
  45. {
  46. if(!x) x=New();
  47. if(l==r) return tre[x].dat+=val,void();
  48. int mid=(l+r)>>1;
  49. if(pos<=mid) insert(ls,l,mid,pos,val);
  50. else insert(rs,mid+1,r,pos,val);
  51. push_up(x);
  52. }
  53. inline int merge(int x,int y)
  54. {
  55. if(!x||!y) return x|y; tre[x].dat+=tre[y].dat; sta.push_back(y);
  56. ls=merge(ls,tre[y].l); rs=merge(rs,tre[y].r); return x;
  57. }
  58. inline int query(int x,int l,int r,int L,int R)
  59. {
  60. if(!x||L>R) return 0;
  61. if(L<=l&&r<=R) return tre[x].dat;
  62. int mid=(l+r)>>1;ll sum=0;
  63. if(L<=mid) sum+=query(ls,l,mid,L,R);
  64. if(R>mid) sum+=query(rs,mid+1,r,L,R);
  65. return sum;
  66. }
  67. void dfs(int x)
  68. {
  69. insert(root[x],1,lim,s[x],1);
  70. for(int i=head[x];i;i=nxt[i])
  71. {
  72. if(ver[i]==fa[x]) continue; fa[ver[i]]=x; dfs(ver[i]);
  73. root[x]=merge(root[x],root[ver[i]]),root[ver[i]]=0;
  74. }
  75. int temp=query(root[x],1,lim,1,s[x]-1); ans[1]+=temp; if(x==1) return ;
  76. ans[x]-=temp+query(root[x],1,lim,1,s[fa[x]]-1);
  77. }
  78. void dfs2(int x){ans[x]+=ans[fa[x]]; for(int i=head[x];i;i=nxt[i]) if(ver[i]!=fa[x]) dfs2(ver[i]);}
  79. int main()
  80. {
  81. freopen("tears.in","r",stdin); freopen("tears.out","w",stdout);
  82. n=read(); m=read();
  83. for(int i=1;i<=n;i++) s[i]=read(),lim=max(lim,s[i]);
  84. for(int i=1,x,y;i<n;i++) x=read(),y=read(),add_edge(x,y),add_edge(y,x);
  85. dfs(1); for(int i=2;i<=n;i++) ans[i]+=query(root[1],1,lim,1,s[i]-1);
  86. dfs2(1); while(m--){int x;x=read();write(ans[x]);putchar('\n');}
  87. return 0;
  88. }

树状数组

  1. #include<bits/stdc++.h>
  2. #define ll long long
  3. #define ull unsigned long long
  4. #define f() cout<<"RP++"<<endl
  5. #define ls tre[x].l
  6. #define rs tre[x].r
  7. using namespace std;
  8. inline int read()
  9. {
  10. int x=0,f=1;char ch=getchar();
  11. while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  12. while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  13. return x*f;
  14. }
  15. inline void write(ll x)
  16. {
  17. #define sta number
  18. int sta[70],top=0; if(x<0) putchar('-'),x=~(x-1);
  19. while(x) sta[++top]=x%10,x/=10; if(!top) sta[++top]=0;
  20. while(top) putchar(sta[top--]+'0');
  21. #undef sta
  22. }
  23. const int N=1e6+10;
  24. int n,m,lim,cnt,s[N],fa[N],lsh[N],pre[N];
  25. int tot=1,head[N],ver[N<<1],nxt[N<<1];
  26. struct BIT
  27. {
  28. int tre[N];
  29. inline int lowbit(int x){return x&(-x);}
  30. void insert(int x){for(int i=x;i<=lim;i+=lowbit(i))tre[i]++;}
  31. int query(int x){int sum=0;for(int i=x;i>0;i-=lowbit(i))sum+=tre[i];return sum;}
  32. }T;
  33. ll ans[N];
  34. void add_edge(int x,int y)
  35. {
  36. ver[++tot]=y;
  37. nxt[tot]=head[x];
  38. head[x]=tot;
  39. }
  40. void dfs(int x)
  41. {
  42. int tmp1=T.query(s[x]-1),tmp2=T.query(s[fa[x]]-1); T.insert(s[x]);
  43. for(int i=head[x];i;i=nxt[i]) if(ver[i]!=fa[x]) fa[ver[i]]=x,dfs(ver[i]);
  44. int temp=T.query(s[x]-1)-tmp1; ans[1]+=temp;
  45. if(x!=1) ans[x]-=temp+T.query(s[fa[x]]-1)-tmp2;
  46. }
  47. void dfs2(int x){ans[x]+=ans[fa[x]]; for(int i=head[x];i;i=nxt[i]) if(ver[i]!=fa[x]) dfs2(ver[i]);}
  48. int main()
  49. {
  50. freopen("tears.in","r",stdin); freopen("tears.out","w",stdout);
  51. n=read(); m=read();
  52. for(int i=1;i<=n;i++) s[i]=read(),lsh[++cnt]=s[i];
  53. sort(lsh+1,lsh+cnt+1); lim=cnt=unique(lsh+1,lsh+cnt+1)-lsh-1;
  54. for(int i=1;i<=n;i++) s[i]=lower_bound(lsh+1,lsh+cnt+1,s[i])-lsh,pre[s[i]]++;
  55. for(int i=1;i<=cnt;i++) pre[i]+=pre[i-1];
  56. for(int i=1,x,y;i<n;i++) x=read(),y=read(),add_edge(x,y),add_edge(y,x);
  57. dfs(1); for(int i=2;i<=n;i++) ans[i]+=pre[s[i]-1];
  58. dfs2(1); while(m--){int x;x=read();write(ans[x]);putchar('\n');}
  59. return 0;
  60. }

T3 传统艺能

解题思路

线段树维护矩阵乘的题目还是第一次做。。

对于一个以 A 结尾的矩阵,他的对角线都是 1 ,然后第一行也是 1 。 \(A_{i,j}\) 表示以 \(i\) 开头在结尾多一个 \(j\) 的答案,转移方程类似矩阵乘,原因显然。

线段树维护的每一个节点都是一个矩阵,每次区间查询单点修改即可。

code

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. #define ull unsigned long long
  4. #define f() cout<<"RP++"<<endl
  5. #define ls x<<1
  6. #define rs x<<1|1
  7. using namespace std;
  8. inline int read()
  9. {
  10. int x=0,f=1;char ch=getchar();
  11. while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  12. while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  13. return x*f;
  14. }
  15. const int N=1e5+10,mod=998244353;
  16. int n,m;
  17. char s[N];
  18. struct Square
  19. {
  20. int a[4][4];
  21. void clear(){memset(a,0,sizeof(a));}
  22. Square friend operator * (Square x,Square y)
  23. {
  24. Square z; z.clear();
  25. for(int i=0;i<=3;i++) for(int j=0;j<=3;j++) for(int k=0;k<=3;k++) z.a[i][j]+=x.a[i][k]*y.a[k][j];
  26. for(int i=0;i<=3;i++) for(int j=0;j<=3;j++) z.a[i][j]%=mod; return z;
  27. }
  28. }S[4];
  29. struct Segment_Tree
  30. {
  31. Square tre[N<<2];
  32. #define push_up(x) tre[x]=tre[ls]*tre[rs];
  33. void update(int x,int l,int r,int pos,int val)
  34. {
  35. if(l==r) return tre[x]=S[val],void();
  36. int mid=(l+r)>>1;
  37. if(pos<=mid) update(ls,l,mid,pos,val);
  38. else update(rs,mid+1,r,pos,val);
  39. push_up(x);
  40. }
  41. Square query(int x,int l,int r,int L,int R)
  42. {
  43. if(L<=l&&r<=R) return tre[x]; int mid=(l+r)>>1;
  44. if(L<=mid&&R>mid) return query(ls,l,mid,L,R)*query(rs,mid+1,r,L,R);
  45. if(L<=mid) return query(ls,l,mid,L,R); return query(rs,mid+1,r,L,R);
  46. }
  47. }T;
  48. #undef int
  49. int main()
  50. {
  51. #define int long long
  52. freopen("string.in","r",stdin); freopen("string.out","w",stdout);
  53. n=read(); m=read(); scanf("%s",s+1);
  54. for(int i=0;i<=3;i++) S[1].a[i][i]=S[2].a[i][i]=S[3].a[i][i]=1;
  55. for(int i=0;i<=3;i++) S[1].a[1][i]=S[2].a[2][i]=S[3].a[3][i]=1;
  56. for(int i=1;i<=n;i++) T.update(1,1,n,i,s[i]-'A'+1);
  57. while(m--)
  58. {
  59. int opt,l,r,p,ans=0; char ch; opt=read();
  60. if(opt==1){p=read();ch=getchar();T.update(1,1,n,p,ch-'A'+1);continue;}
  61. l=read(); r=read(); Square temp=T.query(1,1,n,l,r);
  62. for(int i=1;i<=3;i++) ans=(ans+temp.a[i][0])%mod; printf("%lld\n",ans);
  63. }
  64. return 0;
  65. }

T4 铺设道路

解题思路

维护一个差分数组,最后消成 0 。

显然的时间就是 \(\sum\limits_{i=1}^n\max(0,s_i)\)

为了让答案尽可能的大,我们需要对于每个点消除距离最近的点,把较远的留给后面。

对于让答案尽可能小的情况反之。

code

  1. #include<bits/stdc++.h>
  2. #define int long long
  3. #define ull unsigned long long
  4. #define f() cout<<"RP++"<<endl
  5. using namespace std;
  6. inline int read()
  7. {
  8. int x=0,f=1;char ch=getchar();
  9. while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
  10. while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
  11. return x*f;
  12. }
  13. const int N=3e5+10,mod=1e9+7;
  14. int n,tim,maxn,minn,head,tail,s[N];
  15. pair<int,int> q[N];
  16. void add(int &x,int y){x+=y;if(x>=mod)x-=mod;}
  17. #undef int
  18. int main()
  19. {
  20. #define int long long
  21. freopen("road.in","r",stdin); freopen("road.out","w",stdout);
  22. n=read(); for(int i=1,pre=0;i<=n;i++) s[i]=read()-pre,pre+=s[i],tim+=max(0ll,s[i]);
  23. head=1; tail=0;
  24. for(int i=1;i<=n;i++)
  25. {
  26. if(s[i]>0){q[++tail]=make_pair(i,s[i]);continue;}
  27. int temp=s[i];
  28. while(temp<0)
  29. {
  30. int x=q[head].first,val=q[head].second;
  31. if(val<=-temp){head++;temp+=val;add(minn,val*(i-x)%mod*(i-x)%mod);continue;}
  32. q[head]=make_pair(x,val+temp); add(minn,-temp*(i-x)%mod*(i-x)%mod); break;
  33. }
  34. }
  35. while(head<=tail) add(minn,q[head].second*(n-q[head].first+1)%mod*(n-q[head].first+1)%mod),head++; head=1; tail=0;
  36. for(int i=1;i<=n;i++)
  37. {
  38. if(s[i]>0){q[++tail]=make_pair(i,s[i]);continue;}
  39. int temp=s[i];
  40. while(temp<0)
  41. {
  42. int x=q[tail].first,val=q[tail].second;
  43. if(val<=-temp){tail--;temp+=val;add(maxn,val*(i-x)%mod*(i-x)%mod);continue;}
  44. q[tail]=make_pair(x,val+temp); add(maxn,-temp*(i-x)%mod*(i-x)%mod); break;
  45. }
  46. }
  47. while(head<=tail) add(maxn,q[head].second*(n-q[head].first+1)%mod*(n-q[head].first+1)%mod),head++;
  48. printf("%lld\n%lld\n%lld",tim,maxn,minn); return 0;
  49. }

NOIP模拟83(多校16)的更多相关文章

  1. Noip模拟83 2021.10.26

    T1 树上的数 有手就能在衡中$OJ$上过,但是$WaitingCoders$不行,就是这样 必须使用$O(n)$算法加上大力卡常,思路就是找子树内没更新的更新,更新过了直接$return$ 1 #i ...

  2. Noip模拟54 2021.9.16

    T1 选择 现在发现好多题目都是隐含的状压,不明面给到数据范围里,之凭借一句话 比如这道题就是按照题目里边给的儿子数量不超过$10$做状压,非常邪门 由于数据范围比较小,怎么暴力就怎么来 从叶子节点向 ...

  3. Noip模拟41 2021.8.16

    T1 你相信引力吗 对于区间的大小关系问题,往往使用单调栈来解决 这道题的优弧和劣弧很烦,考虑将其等价的转化 由于所有的合法情况绕过的弧都不会经过最高的冰锥, 又因为环可以任意亲定起点,这样可以直接把 ...

  4. Noip模拟17 2021.7.16

    我愿称这场考试为STL专练 T1 世界线 巧妙使用$bitset$当作vis数组使用,内存不会炸,操作还方便,的确是极好的. 但是这个题如果不开一半的$bitset$是会炸内存的,因为他能开得很大,但 ...

  5. Noip模拟78 2021.10.16

    这次时间分配还是非常合理的,但可惜的是$T4$没开$\textit{long long}$挂了$20$ 但是$Arbiter$上赏了蒟蒻$20$分,就非常不错~~~ T1 F 直接拿暴力水就可以过,数 ...

  6. NOIP模拟92(多校25)

    前言 所以说这次是 HZOI 多校联测巅峰????(题目,数据过水??) T1 石子合并 解题思路 签到题. 发现我们可以给每个数字附一个正负号,每个数字的贡献就是它本身乘上这个符号. 发现至少应该有 ...

  7. NOIP模拟84(多校17)

    T1 宝藏 解题思路 考场上一眼出 \(nlog^2\) 做法,然后没看见是 1s 3e5 的数据,我竟然以为自己切了?? 考完之后尝试着把二分改为指针的移动,然后就过了??或许是数据水吧,感觉自己的 ...

  8. NOIP模拟85(多校18)

    前言 好像每个题目背景所描述的人都是某部番里的角色,热切好像都挺惨的(情感上的惨). 然后我只知道 T1 的莓,确实挺惨... T1 莓良心 解题思路 首先答案只与 \(w\) 的和有关系,于是问题就 ...

  9. NOIP模拟86(多校19)

    T1 特殊字符串 解题思路 \(f_{i,j}\) 表示前 \(i\) 个字符中结尾为 \(j\) 的最大贡献. 转移枚举当前位置于之前位置结尾的组合加上贡献即可. 对于边界问题,容易发现选择 1 一 ...

随机推荐

  1. python tif转jpg

    在同级目录完成tif和jpg的批量转换 import os import cv2 import numpy as np from osgeo import gdal #数据格式转化 def norma ...

  2. QT 4.7.3 交叉编译环境搭建

    测试平台 宿主机平台:Ubuntu 12.04.4 LTS 目标机:Easy-ARM IMX283 目标机内核:Linux 2.6.35.3 交叉编译器:arm-linux-gcc 4.4.4 tsl ...

  3. adb 常用命令大全(1)- 汇总

    adb 常用命令大全系列 基础命令 查看手机设备信息 应用管理 日志相关 模拟按键输入 其他实用功能

  4. Activiti 学习(二)—— Activiti 流程定义和部署

    概述 在这一节,我们将创建一个 Activit 工作流,并启动这个流程,主要包含以下几个步骤: 定义流程,按照 BPMN 的规范,使用流程定义工具,用流程符号把整个流程描述出来 部署流程,把画好的流程 ...

  5. C语言实现线程池功能

    1. 线程池基本原理 2. 线程池C语言实现 2.1 线程池的数据结构 #include <stdio.h> #include <pthread.h> #include < ...

  6. Nginx rewrite跳转 location匹配

    目录: 一.常用的Nginx 正则表达式 二.location 三.rewrite 一.常用的Nginx 正则表达式 1 ^ :匹配输入字符串的起始位置 2 $ :匹配输入字符串的结束位置 3 * : ...

  7. JAVA安全基础之代理模式(二)

    JAVA安全基础之代理模式(二) 上篇讲到静态代理模式,这时候我们发现,一个代理类只能为一个类服务,如果需要代理的类很多,那么就需要编写大量的代理类,比较繁琐.所以就有了动态代理 动态代理 动态代理的 ...

  8. 【第三篇】- Git 工作流程之Spring Cloud直播商城 b2b2c电子商务技术总结

    Git 工作流程 本章节我们将为大家介绍 Git 的工作流程. 一般工作流程如下: 克隆 Git 资源作为工作目录. 在克隆的资源上添加或修改文件. 如果其他人修改了,你可以更新资源. 在提交前查看修 ...

  9. Nginx总结(九)Nginx服务器高性能优化的配置--轻松实现10万并发访问量

    前面讲了如何配置Nginx虚拟主机,如何配置服务日志等很多基础的内容,大家可以去这里看看nginx系列文章:https://www.cnblogs.com/zhangweizhong/category ...

  10. select后给字段起别名,where和group后不能用,但having后可以

    为什么mysql having的条件表达式可以直接使用select后的别名? SQL语句的语法顺序: FROM -> WHERE -> GROUP BY -> HAVING -> ...