YMOI 2019.6.22
题解 YMOI 2019.6.22
lia麦頔溜了,缺了lia麦頔的排名仅供参考
不过分数还是暴露无遗
T1 邪恶入侵
简易题干:
在三维空间内有一些点,点之间有双向边。每一次询问给出一个m,只有边权小于等于m的边才可以同行。每一次询问需要回答出,从源点可联通的最大点数。
毕竟摆在了T1的位置,再加上最近相关练习不少。考场上还是很顺利的想出了正解
由于答案不强制在线,那么先将询问按m升序排序,然后用并查集维护点之间的联系即可
代码:
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX=1e3+5;
int n,m,src,ecnt;
int fa[MAX],fa_size[MAX];
int pos;
struct data{
ll x,y,z;
}node[MAX];
struct datae{
int u,v; double dis;
}edge[MAX*MAX];
struct dataa{
ll m;int id,ans;
}query[500005];
inline int read();
inline ll readll();
double dis(int,int);
bool cmpd(datae,datae);
bool cmpm(dataa,dataa);
bool cmpi(dataa,dataa);
void init();
int find(int);
void unionn(int,int);
int find_size(int);
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#else
freopen("invade.in","r",stdin);
freopen("invade.out","w",stdout);
#endif
n=read(); m=read(); src=n+1;
for(int i=1;i<=n;++i) node[i].x=readll(),node[i].y=readll(),node[i].z=readll();
for(int i=1;i<=src;++i){
for(int j=i+1;j<=src;++j){
ecnt++;
edge[ecnt].u=i; edge[ecnt].v=j; edge[ecnt].dis=dis(i,j);
}
}
sort(edge+1,edge+1+ecnt,cmpd);
for(int i=1;i<=m;++i) query[i].m=read(),query[i].id=i;
sort(query+1,query+1+m,cmpm);
init();
for(int k=1;k<=m;++k){
while(pos<ecnt&&edge[pos+1].dis<query[k].m){
pos++;
int u=edge[pos].u,v=edge[pos].v;
if(find(u)!=find(v)) unionn(u,v);
}
query[k].ans=find_size(src);
}
sort(query+1,query+1+m,cmpi);
for(int i=1;i<=m;++i) printf("%d\n",query[i].ans-1);
return 0;
}
inline int read(){
char tmp=getchar(); int sum=0; bool flag=false;
while(tmp<'0'||tmp>'9'){
if(tmp=='-') flag=true;
tmp=getchar();
}
while(tmp>='0'&&tmp<='9'){
sum=(sum<<1)+(sum<<3)+tmp-'0';
tmp=getchar();
}
return flag?-sum:sum;
}
inline ll readll(){
char tmp=getchar(); ll sum=0; bool flag=false;
while(tmp<'0'||tmp>'9'){
if(tmp=='-') flag=true;
tmp=getchar();
}
while(tmp>='0'&&tmp<='9'){
sum=(sum<<1)+(sum<<3)+tmp-'0';
tmp=getchar();
}
return flag?-sum:sum;
}
double dis(int a,int b){
return sqrt((node[a].x-node[b].x)*(node[a].x-node[b].x)+(node[a].y-node[b].y)*(node[a].y-node[b].y)+(node[a].z-node[b].z)*(node[a].z-node[b].z));
}
bool cmpd(datae a,datae b){
return a.dis<b.dis;
}
bool cmpm(dataa a,dataa b){
return a.m<b.m;
}
bool cmpi(dataa a,dataa b){
return a.id<b.id;
}
void init(){
for(int i=1;i<=src;++i) fa[i]=i,fa_size[i]=1;
}
int find(int a){
if(fa[a]!=a) return find(fa[a]);
return fa[a];
}
void unionn(int a,int b){
int fa_a=find(a),fa_b=find(b);
fa[fa_a]=fa_b;
fa_size[fa_b]+=fa_size[fa_a];
}
int find_size(int a){
return fa_size[find(a)];
}
T2 魔法照片
这道题在考场自以为想出了正解,结果发现只是个暴力,而且!一失误一分不得!>﹏<
考场的思路是酱紫的:
维护一个平衡树,这样求中位数是一个\(O(\log n)\)。通过S形转移,可以保证每一个节点,最多只会被插入一次,弹出一次。因此总理论复杂度是\(O(n \log n)\),看起来是正解。
但是!考场上我把lson打成了rson,还稀里糊涂地过了样例。。愉悦白给。后来事实证明平衡树由于常数原因,只能过60%的测试点虽然这对我来说已经很满足了
说正解:
题解里说
“中位数最大”使我们想到了二分答案。
那就假装想到了吧。二分需要答案满足单调性,那就特殊地构造一下。将要求的“中位数”,修改为“小于等于中位数”
考虑中位数 x
如果有奇数个数字,则大于x的数字与小于x的数字个数相同
如果有偶数个数字,则大于x的数字与小于x的数字个数相差1
等于x的数字则随意放置。
假设所有大于等于x的数字为1,小于x的数字为-1,则当所有数字的个数大于等于0,则x是小于等于中位数
那么二分答案之后用二维前缀和求一下。复杂度\(O(n\times m \log a)\)
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX=1005;
int n,m,s,l;
int ll,rr=1000000000;
inline int read();
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
#else
freopen("photo.in","r",stdin);
freopen("photo.out","w",stdout);
#endif
n=read(); m=read(); s=read(); l=read();
int w[n+5][m+5],sum[n+5][m+5];
for(int i=0;i<=n;++i) sum[i][0]=0;
for(int i=0;i<=m;++i) sum[0][i]=0;
for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) w[i][j]=read();
while(ll<=rr){
int mid=(ll+rr)>>1;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
sum[i][j]=sum[i][j-1]+sum[i-1][j]-sum[i-1][j-1]+(w[i][j]>=mid?1:-1);
}
}
bool flag=false;
for(int i=1;i<=n-s+1;++i){
for(int j=1;j<=m-l+1;++j){
if(sum[i+s-1][j+l-1]+sum[i-1][j-1]-sum[i+s-1][j-1]-sum[i-1][j+l-1]>=0){
flag=true;
break;
}
}
if(flag) break;
}
if(flag) ll=mid+1;
else rr=mid-1;
}
printf("%d\n",rr);
return 0;
}
inline int read(){
char tmp=getchar(); int sum=0; bool flag=false;
while(tmp<'0'||tmp>'9'){
if(tmp=='-') flag=true;
tmp=getchar();
}
while(tmp>='0'&&tmp<='9'){
sum=(sum<<1)+(sum<<3)+tmp-'0';
tmp=getchar();
}
return flag?-sum:sum;
}
T3 生命曲线
没有丝毫难度的线段树。 ——某F姓嘟锍出题人
事实上相当明显的数据结构题,如果熟练掌握的话难度确实不大
等差数列的处理:
为线段树的每一个节点记录一个首相和斜率,那么其余值都可以快速推算出来。
需要知道的是:两个等差数列之和还是个等差数列
一个更新的时候的小技巧:当确定当前区间与目标区间的时候,首相与斜率便已经确定下来了。因此无需其它复杂的维护,像区间修改那样单纯的修改即可。本人就是用来一大堆自以为高明的修改方式,结果debug到疯
区间取反的处理:
其实类似于线段树的区间乘法。这里,取法相当于特殊地\(\times -1\)
加法无法作用于乘法,但乘法可以作用于加法,因此可以理解为乘法的优先级高于加法。这样更新的时候,加法的lazy_tag随乘法的更新而更新,而乘法的lazy_tag直接作用于区间记录的val值
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAX=5e5+5;
int n,m;
ll init[MAX];
ll val[MAX<<4],lazy_fir[MAX<<4],lazy_del[MAX<<4]; int lazy_rev[MAX<<4];
inline int read();
inline ll readll();
void build(int,int,int);
ll qsum(int,int,int,int,int);
void modify_add(int,int,int,int,int,ll,ll);
void modify_rev(int,int,int,int,int);
void pushdown(int,int,int);
void add(int,int,int,ll,ll,int);
int main(){
#ifndef ONLINE_JUDGE
freopen("test.in","r",stdin);
freopen("test.out","w",stdout);
#else
freopen("life.in","r",stdin);
freopen("life.out","w",stdout);
#endif
n=read(); m=read();
for(int i=1;i<=n;++i) init[i]=readll();
build(1,1,n);
for(int i=1;i<=m;++i){
int type,l,r; ll a,d; type=read();
switch(type){
case 1:
l=read(); r=read(); a=readll(); d=readll();
modify_add(1,1,n,l,r,a,d);
break;
case 2:
l=read(); r=read();
printf("%lld\n",qsum(1,1,n,l,r));
break;
case 3:
l=read(); r=read();
modify_rev(1,1,n,l,r);
break;
}
}
return 0;
}
inline int read(){
char tmp=getchar(); int sum=0; bool flag=false;
while(tmp<'0'||tmp>'9'){
if(tmp=='-') flag=true;
tmp=getchar();
}
while(tmp>='0'&&tmp<='9'){
sum=(sum<<1)+(sum<<3)+tmp-'0';
tmp=getchar();
}
return flag?-sum:sum;
}
inline ll readll(){
char tmp=getchar(); ll sum=0; bool flag=false;
while(tmp<'0'||tmp>'9'){
if(tmp=='-') flag=true;
tmp=getchar();
}
while(tmp>='0'&&tmp<='9'){
sum=(sum<<1)+(sum<<3)+tmp-'0';
tmp=getchar();
}
return flag?-sum:sum;
}
void build(int p,int l,int r){
if(l==r) {val[p]=init[l]; return;}
int mid=(l+r)>>1;
build(p<<1,l,mid); build(p<<1|1,mid+1,r);
val[p]=val[p<<1]+val[p<<1|1];
}
ll qsum(int p,int l,int r,int L,int R){
if(L<=l&&r<=R) return val[p];
pushdown(p,l,r);
int mid=(l+r)>>1; ll ans=0;
if(L<=mid) ans+=qsum(p<<1,l,mid,L,R);
if(mid+1<=R) ans+=qsum(p<<1|1,mid+1,r,L,R);
return ans;
}
void modify_add(int p,int l,int r,int L,int R,ll fir,ll del){
if(L<=l&&r<=R) return add(p,l,r,fir+del*(l-L),del,0);
pushdown(p,l,r);
int mid=(l+r)>>1;
if(L<=mid) modify_add(p<<1,l,mid,L,R,fir,del);
if(mid+1<=R) modify_add(p<<1|1,mid+1,r,L,R,fir,del);
val[p]=val[p<<1]+val[p<<1|1];
}
void modify_rev(int p,int l,int r,int L,int R){
if(L<=l&&r<=R) return add(p,l,r,0,0,1);
pushdown(p,l,r);
int mid=(l+r)>>1;
if(L<=mid) modify_rev(p<<1,l,mid,L,R);
if(mid+1<=R) modify_rev(p<<1|1,mid+1,r,L,R);
val[p]=val[p<<1]+val[p<<1|1];
}
void pushdown(int p,int l,int r){
if(!lazy_fir[p]&&!lazy_del[p]&&!lazy_rev[p]) return;
int mid=(l+r)>>1;
add(p<<1,l,mid,lazy_fir[p],lazy_del[p],lazy_rev[p]);
add(p<<1|1,mid+1,r,lazy_fir[p]+lazy_del[p]*(mid+1-l),lazy_del[p],lazy_rev[p]);
lazy_fir[p]=0; lazy_del[p]=0; lazy_rev[p]=0;
}
void add(int p,int l,int r,ll fir,ll del,int rev){
if(rev) {val[p]=-val[p]; lazy_fir[p]=-lazy_fir[p]; lazy_del[p]=-lazy_del[p];}
val[p]+=(ll)(r-l+1)*fir;
val[p]+=(ll)(r-l)*(r-l+1)/2*del;
lazy_fir[p]+=fir; lazy_del[p]+=del;
lazy_rev[p]=lazy_rev[p]^rev;
}
后记
事实上,本次考试的理想分数应当是:100+60+30=190. 而如果真能达到这个分数,那就是一个相当相当高的分数了。
你太菜了!
YMOI 2019.6.22的更多相关文章
- Beta冲刺(1/7)——2019.5.22
所属课程 软件工程1916|W(福州大学) 作业要求 Beta冲刺(1/7)--2019.5.22 团队名称 待就业六人组 1.团队信息 团队名称:待就业六人组 团队描述:同舟共济扬帆起,乘风破浪万里 ...
- Tensorflow学习笔记2019.01.22
tensorflow学习笔记2 edit by Strangewx 2019.01.04 4.1 机器学习基础 4.1.1 一般结构: 初始化模型参数:通常随机赋值,简单模型赋值0 训练数据:一般打乱 ...
- [2019.03.22] Linux 学习心得(1)
本文关键词:shell 判断.grep正则表达式使用和贪婪匹配理解 1. if [ $a -le $b ], 一开始自学的时候我以为 [ ... ] 就是普通的,语法规定的结构,结果其实人家是&quo ...
- 2019.3.22 JMeter基础操作
1.添加线程组:testplan—添加—线程(用户)Threads(Users) 线程属性值:线程数(虚拟用户数).Rump-up(准备时长:设置所有线程全部启动时间).循环次数(每个线程重复发送请求 ...
- 2019/4/22 kmp模板
题目连接:传送门!!! 这里是从头到尾彻底理解KMP的一篇博客,写的非常好 :https://blog.csdn.net/v_JULY_v/article/details/7041827 题意:输入多 ...
- 2019/4/22 拓扑排序的高效写法. 模板题HDU1285:确定比赛名次
传送门 Problem Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现 ...
- Python脱产8期 Day08 2019/4/22
一.三种字符串 1.普通字符串:u'以字符作为输出单位‘ #print(u‘abc’)#用于显示 2.二进制字符串:b'以字节作为输出单位’#用于传输 3.原义字符串:r‘以字符作为输出单位,原样输 ...
- 2019.3.22 Week 11 : ZigBee power test and field test
Test require Zigbee sample:EFR32MG13 (RF layout has ) Gateway N4010A : 2.5Ghz 1Power test 2Field te ...
- 2019.3.22 Week 12 : ZigBee and T/H chamber test
Test purposes Remove backside center ventilation holes, pls help to conduct climatic chamber test of ...
- 2019.01.22 poj2926 Requirements(状态压缩)
传送门 题意:给一堆五维的点,求最远点对. 思路:跟CF1093G差不多 考虑把正负号状压成一个323232以内的数,然后对于每一类分别求最大最小值再做差更新答案即可. 代码: #include< ...
随机推荐
- C语言表白窗口程序
#include<windows.h> #include<stdio.h> #include<string.h> int main() { char modeCom ...
- webgl(three.js)3D光伏,3D太阳能能源,3D智慧光伏、光伏发电、清洁能源三维可视化解决方案——第十六课
序: 能源是文明和发展的重要保障,人类命运不可避开的话题,无论是战争还是发展,都有它存在的身影.从石器时代到现代文明,人类的能源应用在进步,也在面临能源枯竭的危机与恐惧,而开发与应用可再生能源才是解决 ...
- 如何kill一条TCP连接?
原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介 如果你的程序写得有毛病,打开了很多TCP连接,但一直没有关闭,即常见的连接泄露场景,你可能想要在排查问题的过程中, ...
- 题解 CF327A Flipping Game
前言 数据水的一批,\(\mathcal{O}(n^3)\) 给过我觉得是不应该的. 题意 有一个由 \(0\) 和 \(1\) 组成的序列 \(a_1,a_2,a_3,a_4....,a_n\) . ...
- nordic——nrf52系列SWD设置回读保护
在开发时可能需要回读保护功能,在产品出厂后这个功能可以让你的代码更加安全,无法用SEGGER或者其余方式读取你的代码HEX文件,也就是禁用SWD下载接口.但是SWD锁住了,还想使用(从新下载代码)也是 ...
- nginx+keepalived实现主从模式双机热备份
主从模式就是一台机器提供服务,另一台机器作为备份机,当主机的服务停止时,备份机立刻接替主机的服务. 安装 安装nginx wget http://nginx.org/download/nginx-1. ...
- shardingsphere-jdbc 水平分表学习记录
放在自己博客里搬过来一份~ 前司使用的是自己魔改的TDDL,在家时间比较多就尝试学一些业内比较常用的中间件. 这里记录一下学习中遇到的一些问题. 环境 设置的比较简单(太懒了就测试了几个表), 两个分 ...
- zk系列三:zookeeper实战之分布式锁实现
一.分布式锁的通用实现思路 分布式锁的概念以及常规解决方案可以参考之前的博客:聊聊分布式锁的解决方案:今天我们先分析下分布式锁的实现思路: 首先,需要保证唯一性,即某一时点只能有一个线程访问某一资源: ...
- JAVA系列之类加载机制详解
类的加载机制 ? 双亲委派机制 ? 什么是类加载器 ? 自定义类加载器有哪些应用场景 ? 通常,在关于Java的类加载部分会遇到以上疑问,本文将对类加载重要部分做详细介绍,包括重要的基础概念和应用场景 ...
- nginx日志切割并备份
[root@lecode-pre55 bin]# cat nginx-log.sh #!bin/bash #auther:ansheng #desc: nginx日志备份,注意脚本中文件的路径. #备 ...