T1:农场

题意:有一个长为 $n$ 的序列 $a$,要求将其分成尽可能多的部分,使得每一部分的 $a_i$ 的和相等。求最多能分成的部分数。

$30\%:1\le n\le 1000$

$80\%:1\le n\le 10^5$

$100\%:1\le a_i\le 10,1\le \sum a_i\le 10^6$

这题不难,说一下我在考场的思路:

首先答案应该是 $\sum a_i$ 的约数。那么可以转化一下,变成找到满足要求的最小的和(也是其约数)

进一步想到前缀和。我们发现 $x$ 满足条件,当且仅当 $x,2x,3x\dots$ 全部在前缀和中出现。

于是考场上写了个80分的暴力 $O(n\sqrt{n})$(枚举约数 $O(\sqrt{n})$,判断 $O(n)$)

后来发现可以做到更快:因为总和不超过 $10^6$,因此可以开桶。复杂度 $O(\sigma(n))<O(n\log n)$。

但是 $O(n\sqrt{n})$ 可以过?

 #include<bits/stdc++.h>
using namespace std;
int n,sum;
int fac[],fl;
bool vis[];
void split(int x){ //求出总和的所有约数
for(int i=;i*i<=x;i++)
if(x%i==){
fac[++fl]=i;
if(i*i!=x) fac[++fl]=x/i;
}
sort(fac+,fac+fl+);
}
int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
int a;
scanf("%d",&a);
sum+=a;
vis[sum]=true; //对前缀和开桶
}
split(sum);
for(int i=;i<=fl;i++){
bool flag=true;
for(int j=fac[i];j<=sum;j+=fac[i]) //判断是否满足
if(!vis[j]){ //不满足
flag=false;break;
}
if(flag){
printf("%d\n",sum/fac[i]);return ; //答案为总和/单个和=段数
}
}
}

T2:密码锁

题意:有一个长为 $n$ 的序列 $a$,每一次操作可以让区间 $[l,r]$ 间所有 $a_i$ 加一或所有 $a_i$ 减一 $\pmod m$。问最少多少次操作可以让序列变为全 $0$。

测试点 1~4:$1\le n\le 4,2\le m\le 10$

测试点 5~9: $1\le n\le 10^5,2\le m\le 3$

测试点 10~15:$2\le n,m\le 3000$

测试点 16~18:$2\le n\le 2\times 10^5$

全部20个测试点:$1\le n\le 10^6,2\le m\le 10^9$

这题很有思维难度。像我这种考场上连20分BFS都没想到,写了个 $\sum\min(a_i,m-a_i)$ 的……居然还有5分

看到区间加减操作,想到差分(设为 $d,d_i=(a_i-a_{i-1})\operatorname{mod}m(i\le n),d_{n+1}=m-a_n$)。

把 $a_{i-1}$ 进行 $d_i$ 次加操作后可以变成 $a_i$,或者进行 $m-d_i$ 次减操作后可以变成 $a_i$。

所以想到一个贪心:优先对 $d_i$ 小的进行加操作,剩下的进行减操作。

而对一个区间 $[l,r]$ 进行 $x$ 次操作实际上就是 $d_l-=x,d_{r+1}+=x$,整个序列变为 $0$ 就是 $d$ 变为全 $0$。

又因为每次操作都是一加一减,所以对 $d$ 进行的加操作次数等于减操作次数。

那么问题的本质就是把 $d_i$ 进行分组,使得第一组的 $\sum d_i$ 等于第二组的 $\sum m-d_i$。此时答案也就是这个相等的和。

结合刚刚那个贪心的想法,只需要把 $d_i$ 排序,枚举断点 $p$,分成 $i\le p$ 和 $i>p$ 两组。当这两组的和相等时这个和就是答案。

直接枚举断点再求和还不够,加上前缀和和后缀和就可以了。复杂度 $O(n\log n)$。

注:$d_{n+1}=m-a_n$ 一定也要考虑,否则会导致 $[l,n]$ 的操作没有意义。

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,m,a[],dif[]; //dif是差分
ll sum,pre[]; //pre是差分排序后的前缀和
int main(){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
scanf("%d",a+i);
dif[i]=(a[i]-a[i-]+m)%m;
}
dif[n+]=(m-a[n])%m; //注意,这个不能漏
sort(dif+,dif+n+);
for(int i=;i<=n+;i++) pre[i]=pre[i-]+dif[i]; //做前缀和
for(int i=n+;i>=;i--){
sum+=m-dif[i]; //做后缀和
if(sum==pre[i-]){ //前缀和和后缀和相等,这就是答案
printf("%lld\n",sum);return ;
}
}
}

T3:涛涛摘苹果

题意:有一棵 $n$ 个节点的苹果树,根节点为 $1$,初始每个点都有一个重为 $a_i$ 的苹果。每天早上根节点的苹果会消失。每天下午所有苹果都会下落一层(也就是下落到它的父亲节点上)。某些天(第 $t$ 天)的晚上编号 $x$ 的点上会多长出一个重为 $w$ 的苹果,这样的操作共有 $m$ 个。某些天(第 $t$ 天)早晨根节点苹果消失前会询问以 $x$ 为根的子树中所有苹果的重量之和,共有 $q$ 个询问。

$10\%:$ 所有输入数据都不超过 $5000$

另 $10\%:$ 树退化成一条链,其中 $i$ 与 $i-1$ 有边

另 $20\%:$ 所有询问满足 $x=1$

另 $20\%:m=0$

$100\%:$ 所有输入数据都不超过 $10^5$

先考虑 $m=0$ 怎么做:

我们发现苹果 $x$ 对第 $t$ 天在节点 $y$ 的询问产生贡献,当且仅当:($sz[x]$ 表示 $x$ 的子树大小,$dfn[x]$ 表示 $x$ 的dfs序,$dep[x]$ 表示 $x$ 的深度)

$dep[x]\ge dep[y]+t-1$

$dfn[y]\le dfn[x]\le dfn[y]+sz[y]-1$

那么就可以乱搞了。(既然不是正解,不说做法了,其实是我不会)

$m\ne 0$ 时,根据条件 $1$,我们发现添加的苹果 $x$ 相较其它苹果少下落了 $t$ 天,可以想象从 $x$ 新连出一个节点 $y$,使得 $dep[y]=dep[x]+t$,也就是从 $x$ 连出一条权 $t$ 的边。

根据条件 $2$,他应该在子树内,连出一条边恰好符合要求。

但这样不够,还有一个时间限制!只有添加操作的 $t\le$ 询问操作的 $t-1$,才能产生贡献。

现在是个三维偏序,CDQ即可。

时间复杂度:$O((n+m+q)\log^2(n+m+q))$

 #include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
inline int read(){
char ch=getchar();int x=,f=;
while(ch<'' || ch>'') f|=ch=='-',ch=getchar();
while(ch>='' && ch<='') x=x*+ch-'',ch=getchar();
return f?-x:x;
}
int n,m,q,cnt;
int el,head[maxn*],to[maxn*],w[maxn*],nxt[maxn*];
int dep[maxn*],sz[maxn*],dfn[maxn*];
ll ans[maxn],bit[maxn*];
struct oper{ //tp=0表示修改,tp=1表示询问,tim表示时间,x表示节点,w表示权值(可能没有),id表示原编号
int tp,tim,x,w,id;
}op[maxn*];
inline void add(int u,int v,int w_){
to[++el]=v;w[el]=w_;nxt[el]=head[u];head[u]=el;
}
inline bool cmptim(const oper &o1,const oper &o2){ //注意只有修改会对询问产生贡献,所以时间一样的要把修改放前面
if(o1.tim!=o2.tim) return o1.tim<o2.tim;
return o1.tp<o2.tp;
}
inline bool cmpdep(const oper &o1,const oper &o2){
return dep[o1.x]>dep[o2.x];
}
inline bool cmphhh(const oper &o1,const oper &o2){ //各种排序
return dep[o1.x]+o1.tim>dep[o2.x]+o2.tim;
}
inline void modify(int p,int v){
for(;p<=n+m;p+=p&-p) bit[p]+=v;
}
inline ll query(int p){
ll ans=;for(;p;p-=p&-p) ans+=bit[p];return ans;
}
inline ll query(int l,int r){
return query(r)-query(l-);
} //以上树状数组
void dfs(int u,int f){ //预处理dep,dfn,sz
sz[u]=;dfn[u]=++cnt;
for(int i=head[u];i;i=nxt[i]){
int v=to[i];
if(v==f) continue;
dep[v]=dep[u]+w[i];
dfs(v,u);sz[u]+=sz[v];
}
}
void CDQ(int l,int r){ //CDQ分治
if(l==r) return;
int mid=(l+r)>>;
CDQ(l,mid);CDQ(mid+,r);
sort(op+l,op+mid+,cmpdep); //左边按照dep排序
sort(op+mid+,op+r+,cmphhh); //右边按照dep+time排序
int cl=l;
FOR(i,mid+,r){
for(;cl<=mid && dep[op[cl].x]>=dep[op[i].x]+op[i].tim-;cl++) //cl能对i产生贡献
if(op[cl].tp==) modify(dfn[op[cl].x],op[cl].w); //是修改,插入树状数组
if(op[i].tp==) ans[op[i].id]+=query(dfn[op[i].x],dfn[op[i].x]+sz[op[i].x]-); //是询问,添加贡献
}
FOR(i,l,cl-) if(op[i].tp==) modify(dfn[op[i].x],-op[i].w); //清空树状数组
}
int main(){
n=read();m=read();q=read();
FOR(i,,n) op[i]=(oper){,,i,read(),}; //一开始的苹果也可以看成是添加操作
FOR(i,,n-){
int u=read(),v=read();
add(u,v,);add(v,u,); //边权为1
}
FOR(i,,m){
int t=read(),x=read(),w=read();
add(x,i+n,t); //连虚边
op[i+n]=(oper){,t+,i+n,w,}; //添加操作(把时间设为t+1会更方便排序)
}
FOR(i,,q){
int t=read(),x=read();
op[i+n+m]=(oper){,t,x,,i}; //询问操作
}
dfs(,);
sort(op+,op+n+m+q+,cmptim); //按时间排序
CDQ(,n+m+q);
FOR(i,,q) printf("%lld\n",ans[i]);
}

T4:小学生图论题

题意:给出一个 $n$ 个点的有向竞赛图。有 $m$ 条链,第 $i$ 条长 $k_i$,依次经过 $a_1,a_2,\dots,a_{k_i}$。这些链没有公共点。链上所有边的方向已知,为链经过的方向,其他边方向等概率随机。求这个图强联通分量的期望个数对 $998244353$ 取模。

测试点 1~2:$1\le n\le 1000,m=0$

测试点 3~4:$1\le n,m\le 1000$

测试点 5:$k_i=2$

全部10个测试点:$1\le n,m\le 10^5,2\le k_i\le n,\sum k_i\le n$

不会做。

有朝一日会做了再来填坑吧……

GDOI2018 Day1 题目总结的更多相关文章

  1. [gdoi2018 day1]小学生图论题【分治NTT】

    正题 题目大意 一张随机的\(n\)个点的竞赛图,给出它的\(m\)条相互无交简单路径,求这张竞赛图的期望强联通分量个数. \(1\leq n,m\leq 10^5\) 解题思路 先考虑\(m=0\) ...

  2. contesthunter CH Round #64 - MFOI杯水题欢乐赛day1 solve

    http://www.contesthunter.org/contest/CH Round %2364 - MFOI杯水题欢乐赛 day1/Solve Solve CH Round #64 - MFO ...

  3. 【GDOI】2018题目及题解(未写完)

    我的游记:https://www.cnblogs.com/huangzihaoal/p/11154228.html DAY1 题目 T1 农场 [题目描述] [输入] 第一行,一个整数n. 第二行,n ...

  4. [51nod1357]密码锁

    有一个密码锁,其有N位,每一位可以是一个0~9的数字,开启密码锁需要将锁上每一位数字转到解锁密码一致.这个类似你旅行用的行李箱上的密码锁,密码锁的每一位其实是一个圆形转盘,上面依次标了0,1,...9 ...

  5. [题解]玩具谜题(toy)

    玩具谜题(toy) 来源:noip2016 提高组 day1 [题目描述] 小南有一套可爱的玩具小人, 它们各有不同的职业. 有一天, 这些玩具小人把小南的眼镜藏了起来. 小南发现玩具小人们围成了一个 ...

  6. [51nod1357]密码锁 暨 GDOI2018d1t2

    有一个密码锁,其有N位,每一位可以是一个0~9的数字,开启密码锁需要将锁上每一位数字转到解锁密码一致.这个类似你旅行用的行李箱上的密码锁,密码锁的每一位其实是一个圆形转盘,上面依次标了0,1,...9 ...

  7. 【心情】HNOI2018游记

    Day 0. 全机房的人好像都在做题.然而下午是社团节的游园会,身为社干的我风风雨雨在外面各种搬凳子搬椅子换场地招待外校同学……就这样我好像什么都没有复习. 晚上就一起去酒店了.大概因为是高一的缘故, ...

  8. HNOI2019爆零记

    HNOI2019真-爆零祭 我怎么这么菜QAQ day-37 从学科溜过来搞OI. 班主任一直在谈论我退役的事情,这就是NOIP挂分的后果...说我没考好就找理由,人家xxxxxxx可不是xxxxxx ...

  9. 2019.7 佳木斯培训A层

    day1题目及题解 day2题目及题解 day3题目及题解 day4题目及题解 day5题目及题解

随机推荐

  1. TClientDataSet 提交时提示 Field value Required 但是未提示具体哪个字段。

    TClientDataSet 提交时提示 Field value Required 但是未提示具体哪个字段. 这个错误特别麻烦,要使用 midas 控件时,虽然很方便.但是出错了根本找不到原因,特别是 ...

  2. tensorflow batch

    这两天一直在看tensorflow中的读取数据的队列,说实话,真的是很难懂.也可能我之前没这方面的经验吧,最早我都使用的theano,什么都是自己写.经过这两天的文档以及相关资料,并且请教了国内的师弟 ...

  3. Hadoop日记Day11---主从节点接口分析

    一.NameNode 的接口分析 1. NameNode本质 经过前面的学习,可以知道NameNode 本身就是一个java 进程.观察RPC.getServer()方法的第一个参数,发现是this, ...

  4. Kubernetes学习之路目录

    Kubernetes基础篇 环境说明 版本说明 系统环境 Centos 7.2 Kubernetes版本 v1.11.2 Docker版本 v18.09 Kubernetes学习之路(一)之概念和架构 ...

  5. Gitlab+Jenkins学习之路(十四)之自动化脚本部署实践

    目录 一.环境说明和准备 1.环境说明 2.服务器准备工作 二.发布脚本编写 1.自动化部署流程设计 2.自动化部署脚本编写 三.发布测试 1.开发机和github添加ssh信任 2.克隆项目到开发机 ...

  6. docker之Dokcerfile 常用指令

    一.Docker语法 Docker语法: FROM 基础镜像base image RUN 执行命令 ADD 添加文件 COPY 拷贝文件 CMD 执行命令 EXPOSE 执行命令 WORKDIR 指定 ...

  7. pie的绕过方式

    目标程序下载 提取码:qk1y 1.检查程序开启了哪些安全保护机制 pie机制简介 PIE(position-independent executable) 是一个针对代码段.text, 数据段.*d ...

  8. 面向 Photoshop 的英特尔® Texture Works 插件

    英特尔对 Photoshop* 进行了扩展,以通过插件充分利用最新的图像压缩方法 (BCn/DXT).该插件旨在为图形工作者提供一款获取卓越压缩结果的工具,并提高 Photoshop* 中的压缩速度. ...

  9. 学习 google file system 心得体会

    Google File system文件系统,是在特别便宜的普通硬件设备上运行,它是一个面向大规模数据密集型运用的.可伸缩的分布式文件系统. 与传统文件相比,它认为组件失效是很平常的事件,因为GFS包 ...

  10. JWT总结

    Json web token (JWT) 什么是JWT? Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该toke ...