考前

mtr 中午拿着笔记本改题(Orz),一点多发现 13.50 有比赛(截止 12 点都没放出来),赶紧睡。13.40 到了学校,巨瞌睡,洗了把脸到机房发现推迟到 14.30 了,wcnm

趴在桌上睡觉,Orz 抓紧时间打 luogu 月赛的大佬

考场

T1 集体讨论得 dead line 是直线,感觉有点像《仪仗队》,打出 \(n,m\le3\) 的表发现似乎可以枚举以形成直线的两点为对角的矩形算,跳了

T2 想到了正确性不明 \(O(n\log^2 n)\) 点分治,但本人分治学的很烂就没准备写(ys 巨佬考场就写了出来,切了),想到了从大到小加点,并查集维护直径,但不知道如果直径不过当前点怎么办,跳了跳了

T3 一眼线段树求没有花精的区间中最长的,稍微划拉了一下如何 up,感觉可做,毕竟数据结构算是我的强项

怕 T3 写不完,15.20 就开始写了。

回来看 T1,先写完了假做法,发现在 \(3\times4\) 的时候就挂了,看上去要容斥。又开始尝试每次以最下、最右的点为一个端点,用欧拉函数算贡献,然后把这些点去掉,但想不清楚,最后写了暴力跑路

T2 裸暴力

大概 16.00 开始写 T3,先手推清楚了具体如何 up,问题是在线段树的每个节点上开了个结构体(重载小于号),常数巨大。17.00 写完,调了调边界就过了小样例,发现就这个题没大样例。。。只能对拍。结果没拍几组就挂了。慌得一比,调小数据发现比较区间哪个优是不能直接比区间中点到两边的距离,因为 \(0,n+1\) 两个位置上没有花精,改了改重载小于号终于在 17.20 过拍了。。。

交题时怕 T1 MLE,\(N\) 从 \(2\times10^7\) 改到了 \(40^4\)。最后又觉得能多骗分,想着平时能开 \(5\times10^7\) 个 int,于是开到了 \(10^7\)

res

rk1 0+55+100

T1 MLE。平时能恰好开 \(6\times10^7\) 个 int 是因为有 256M,但这题只有 128M。。。

T2 卡常过了一些点

rk2 赵旭兵 60+30+60

rk6 ys 0+100+0

夜莺与玫瑰

枚举方向向量 \((i,j)\),显然有 \(\gcd(i,j)=1\),设这条直线与给定矩形的点的交点为 \((x,y)\),那就统计满足 \((x-i,y-j)\) 在矩形内,\((x+i,y+j)\) 不在矩形内的 \((x,y)\)(即 \((x,y)\) 是这条直线与矩形的最后一个交点,下图中蓝色)。不难算出答案为:

\[\sum_{i=1}^{n-1}\sum_{j=1}^{m-1}[\gcd(i,j)=1](n-i)(m-j)-\max(n-2i,0)\times\max(m-2j,0)
\]
\[=\sum_{i=1}^{n-1}\sum_{j=1}^{m-1}[\gcd(i,j)=1](nm-im-jn+ij)+\sum_{i=1}^{n/2}\sum_{j=1}^{m/2}[\gcd(i,j)=1](-nm+2im+2jn-4ij)
\]

理解:

首先 \(i,j\) 要互质,其次 \((x-i,y-j)\) 在矩形内的 \((x,y)\) 有 \((n-i)(m-j)\) 个(黄色+蓝色),\((x+i,y+j)\) 也在矩形内的有 \((n-2i)(m-2j)\) 个(黄色),容斥一下即可。



由于 \(n\le4000\),可以二维前缀和预处理答案。一个问题是需要卡空间,一个大问题是数据中有 \(n,m=4001\) 的点,出题人我问候你。

基于这个相同的式子,有时间 \(O(n^2+Tn)\),空间 \(O(n^2)\) 的做法

基于莫比乌斯反演,有时间 \(O(n+Tn)\),空间 \(O(n)\) 的做法。

code
#define int unsigned
const int N = 4004, mod = (1<<30)-1;
int T,n,m; int ans[N+8][N+8],a[N+8][N+8];
bitset<N+8> is[N+8]; signed main() {
// freopen("a.in","r",stdin);
// freopen("a.out","w",stdout);
is[1][0] = 1;
For(i,1,N) For(j,1,N) is[i][j] = is[min(i,j)][max(i,j)%min(i,j)];
////////// nm项 ij项
For(i,1,N-1) For(j,1,N-1) if( is[i][j] ) {
++ans[i+1][j+1], a[i+1][j+1] += i*j;
if( i < 2e3+2 && j < 2e3+2 )
--ans[i<<1|1][j<<1|1], a[i<<1|1][j<<1|1] -= 4*i*j;
}
For(i,1,N) For(j,1,N)
ans[i][j] += ans[i-1][j] + ans[i][j-1] - ans[i-1][j-1],
a[i][j] += a[i-1][j] + a[i][j-1] - a [i-1][j-1];
// ans[n][m]: gcd(1..n,1..m)=1的个数(nm项的系数)
// a[n][m]: ij项
For(i,1,N) For(j,1,N) ans[i][j] = ans[i][j]*i*j + a[i][j];
////////// im项 jn项
memset(a,0,sizeof a);
For(i,1,N-1) For(j,1,N-1) if( is[i][j] ) {
a[i+1][j+1] -= i;
if( i < 2e3+2 && j < 2e3+2 ) a[i<<1|1][j<<1|1] += i<<1;
}
For(i,1,N) For(j,1,N)
a[i][j] += a[i-1][j] + a[i][j-1] - a[i-1][j-1],
// a[n][m]: i in [1,n],j in [1,m],gcd(i,j)=1的i的和
ans[i][j] += j*a[i][j]; // 此处的j为式子中的m
memset(a,0,sizeof a);
For(i,1,N-1) For(j,1,N-1) if( is[i][j] ) {
a[i+1][j+1] -= j;
if( i < 2e3+2 && j < 2e3+2 ) a[i<<1|1][j<<1|1] += j<<1;
}
For(i,1,N) For(j,1,N)
a[i][j] += a[i-1][j] + a[i][j-1] - a[i-1][j-1],
ans[i][j] += i*a[i][j];
read(T);
while( T-- ) {
read(n,m);
// assert(n<=4000),assert(m<=4000);
write((n+m+2*ans[n][m])&mod);
}
return ioclear();
}

影子

考场上其实想的差不多

每次合并完并查集后,用当前点点权乘上直径更新答案即可。因为是用当前点来合并连通块,因此如果直径的两个端点在原来的联通块中,那么这次的答案一定不比那时算出来的优(点权不会变大);否则直径一定会过当前点

code
const int N = 1e5+5;
int T,n,mm,val[N],head[N];
struct Edge { int to,w,nxt; } e[N*2]; int id[N];
struct DSU {
int fa,p,q;
LL d;
} s[N]; namespace dist {
int fa[N],dep[N],siz[N],son[N],top[N];
LL d[N];
void dfs1(int u,int f) {
dep[u] = dep[ fa[u]=f ]+1, siz[u] = 1, son[u] = 0;
for(int i = head[u], v; i; i = e[i].nxt) if( (v=e[i].to) != f ) {
d[v] = d[u] + e[i].w;
dfs1(v,u);
siz[u] += siz[v];
if( siz[v] > siz[son[u]] ) son[u] = v;
}
}
void dfs2(int u,int t) {
top[u] = t;
if( son[u] ) dfs2(son[u],t);
for(int i = head[u], v; i; i = e[i].nxt)
if( (v=e[i].to) != fa[u] && v != son[u] ) dfs2(v,v);
}
void init() { dfs1(1,0), dfs2(1,1); }
int lca(int u,int v) {
while( top[u] != top[v] ) {
if( dep[top[u]] < dep[top[v]] ) swap(u,v);
u = fa[top[u]];
}
return dep[u]<dep[v] ? u : v;
}
LL dis(int u,int v) { return d[u]+d[v]-d[lca(u,v)]*2; }
}
using dist::dis; int find(int x) { return s[x].fa==x ? x : s[x].fa=find(s[x].fa); }
void up(int x,int p,int q) {
LL d = dis(p,q);
if( d > s[x].d ) s[x].p = p, s[x].q = q, s[x].d = d;
}
void merge(int x,int y) {
if( x == y ) return;
s[y].fa = x;
int p = s[x].p, q = s[x].q;
up(x,s[y].p,s[y].q);
up(x,p,s[y].p), up(x,p,s[y].q), up(x,q,s[y].p), up(x,q,s[y].q);
} void solve() {
LL ans = 0;
read(n);
For(i,1,n) read(val[i]), id[i] = i, s[i] = (DSU){i,i,i,0};
for(int i = 1; i < n; ++i) {
int x,y,z; read(x,y,z);
e[++mm] = (Edge){y,z,head[x]}, head[x] = mm;
e[++mm] = (Edge){x,z,head[y]}, head[y] = mm;
}
dist::init();
sort(id+1,id+n+1,[](const int &x,const int &y){return val[x]>val[y];});
For(i,1,n) {
int u = id[i];
for(int j = head[u], v; j; j = e[j].nxt)
if( val[ v=e[j].to ] >= val[u] ) merge(find(u),find(v));
ans = max(ans,val[u]*s[find(u)].d);
}
write(ans,10);
} signed main() {
read(T);
while( T-- ) {
mm = 1;
mem(head,0,n);
solve();
}
return ioclear();
}

点分治做法(虽然时间、代码复杂度被爆踩)

玫瑰花精

线段树

考场 code
const int N = 2e5+5, M = 1e6+5;
int n,m; int pos[M];
struct Seg {
int l,r;
int len() {
if( l == 1 ) return r;
if( r == n ) return n-l+1;
return (l+r>>1)-l+1;
}
Seg(int l=0,int r=0):l(l),r(r){}
};
bool operator < (Seg x,Seg y)
{ return x.len()!=y.len() ? x.len()>y.len() : x.l<y.l; } struct Node {
int l,r,lr,rl;
// lr: 从左往右最后一个没占的地方
Seg a;
} t[N*4];
void up(int u) {
int ls = u<<1, rs = u<<1|1;
if( t[ls].lr == t[ls].r && t[rs].lr ) t[u].lr = t[rs].lr;
else t[u].lr = t[ls].lr;
if( t[rs].rl == t[rs].l && t[ls].rl <= n ) t[u].rl = t[ls].rl;
else t[u].rl = t[rs].rl;
t[u].a = min(t[ls].a,t[rs].a);
t[u].a = min(t[u].a,Seg(min(t[ls].rl,t[rs].l),max(t[rs].lr,t[ls].r)));
}
void build(int u,int l,int r) {
t[u].l = l, t[u].r = r;
if( l == r ) {
t[u].lr = t[u].rl = l;
t[u].a = Seg(l,l);
return;
}
int mid = l+r>>1;
build(u<<1,l,mid), build(u<<1|1,mid+1,r);
up(u);
// printf("> %d %d: %d %d %d %d\n",l,r,t[u].lr,t[u].rl,t[u].a.l,t[u].a.r);
}
void modify(int u,int p,bool x) {
if( t[u].l == t[u].r ) {
if( x ) t[u].lr = 0, t[u].rl = n+1, t[u].a = Seg(n+1,0);
else t[u].lr = t[u].rl = t[u].l, t[u].a = Seg(t[u].l,t[u].l);
return;
}
int ls = u<<1, rs = ls|1;
modify( p<=t[ls].r?ls:rs ,p,x);
up(u);
} signed main() {
// freopen("c.in","r",stdin);
// freopen("c.out","w",stdout);
read(n,m);
build(1,1,n);
while( m-- ) {
int op,x; read(op,x);
if( op == 1 ) {
Seg a = t[1].a;
if( a.l == 1 ) pos[x] = 1;
else if( a.r == n ) pos[x] = n;
else pos[x] = a.l+a.r>>1;
modify(1,pos[x],1);
write(pos[x]), putc(10);
} else modify(1,pos[x],0);
}
return ioclear();
}

20210714 noip15的更多相关文章

  1. [Luogu 2678] noip15 子串

    [Luogu 2678] noip15 子串 题目描述 有两个仅包含小写英文字母的字符串 A 和 B.现在要从字符串 A 中取出 k 个互不重叠的非空子串,然后把这 k 个子串按照其在字符串 A 中出 ...

  2. noip15

    童话故事专场 T1 首先,dead line 是一条直线,而不是线段.考试的时候一直以为是线段,那么横竖共有n+m条,考虑斜着的,斜着的交点为有穷的,则需要满足斜率不同,那么只需要统计一边的,再乘2就 ...

  3. 调用免费API查询全年工作日、周末、法定节假日、节假日调休补班数据

    前言 日常开发中,难免会用到判断今天是工作日.周末.法定节假日.节假日调休补班做一些业务处理,例如:仅在上班时间给用户推送消息.本文记录调用免费API查询全年工作日.周末.法定节假日.节假日调休补班数 ...

  4. B 站崩了,总结下「高可用」和「异地多活」

    你好,我是悟空. 一.背景 不用想象一种异常场景了,这就真实发生了:B 站晚上 11 点突然挂了,网站主页直接报 404. 手机 APP 端数据加载不出来. 23:30 分,B 站做了降级页面,将 4 ...

  5. 备战-Java 基础

    备战-Java 基础 仰天大笑出门去,我辈岂是蓬蒿人. 简介:备战-Java 基础. 一.基本数据类型 1.Java基本数据类型 基本数据类型有8种:byte.short.int.long.float ...

  6. 关于Hadoop调优

    Hadoop生产调优 一.HDFS-核心参数 1.NameNode 内存生产配置 1) NameNode 内存计算 每个文件块大概占用 150byte,一台服务器 128G 内存为例,能存储多少文件块 ...

  7. webpack 快速入门 系列 —— 性能

    其他章节请看: webpack 快速入门 系列 性能 本篇主要介绍 webpack 中的一些常用性能,包括热模块替换.source map.oneOf.缓存.tree shaking.代码分割.懒加载 ...

  8. Java 中节省 90% 时间的常用的工具类

    前言 你们有木有喜欢看代码的领导啊,我的领导就喜欢看我写的代码,有事没事就喜欢跟我探讨怎么写才最好,哈哈哈...挺好. 今天我们就一起来看看可以节省 90% 的加班时间的第三方开源库吧,第一个介绍的必 ...

  9. Java基础——逻辑运算符、位运算符

    逻辑运算符.位运算符.三元运算符 逻辑运算符  public class Demon05 {     public static void main(String[] args) {          ...

随机推荐

  1. 大数据学习(04)——MapReduce原理

    前两篇文章介绍了HDFS的原理和高可用,下面再来介绍Hadoop的另外一个模块MapReduce.它的思想是很多技术的鼻祖,值得一学. MapReduce是什么 MapReduce是一个分布式计算系统 ...

  2. Git基本理论---重点

    Git本地有三个工作区域: 工作目录(Working Directory): 存放项目代码 暂存区(Stage/Index) : 临时存放文件的改动,保存的是文件列表信息 资源库 (Repositor ...

  3. SQL遍历日期

    IF OBJECT_ID(N'tempdb..#temp', N'U') IS NOT NULL BEGIN DROP TABLE #temp;--临时表删除 END --创建临时表 CREATE T ...

  4. 那些 Unix 命令替代品们「GitHub 热点速览 v.21.32」

    作者:HelloGitHub-小鱼干 好用的 Unix 命令替代工具能让你事半功倍,例如,bat 便是个带着高亮特性的加强版 cat,就像你用了 oh my zsh 之后便会感受到它的强大.同样好用的 ...

  5. 刷到血赚!字节跳动内部出品:722页Android开发《360°全方面性能调优》学习手册首次外放,附项目实战!

    前言 我们平时在使用软件的过程中是不是遇到过这样的情况:"这个 app 怎么还没下载完!"."太卡了吧!"."图片怎么还没加载出来!".&q ...

  6. 『Java』接口的使用方法

    以下三个文件存在于同一个包下: 定义接口Dome_Interface.java: package cn.xxmmqg.Interface; // 接口不能直接使用,必须有一个"实现类&quo ...

  7. Manage Historical Snapshots in Sonarqube

    Login as admin, go to a dashboard of a project, then click "Configuration -> History" a ...

  8. Django静态文件配置 request对象 Django操作MySQL

    Django中的文件介绍 render.HttpResponse和redirect 当我们想起手写一个项目,创建好应用并且注册之后,在urls.py文件先导入app文件夹下migrations下的vi ...

  9. Android 9.0 默认输入法的设置流程分析

    Android 输入法设置文章 Android 9.0 默认输入法的设置流程分析 Android 9.0 添加预置第三方输入法/设置默认输入法(软键盘) 前言 在上一篇文章  Android 9.0 ...

  10. noip42

    T1 朴素dp很好想,设 \(dp_{u,0/1}\) ,表示以 \(u\) 为根的子树,选/不选 \(u\) 所产生的最大贡献. 转移方程则有, \[dp_{u,0} = \prod_{v\in s ...