【集训第三天·疯狂训练】哦,顺带学习了manacher
虽然说是疯狂训练吧,但是也没写多少题,就把伸展树的操作熟悉了一下,ac了5个题目。
一整天没啥可吐槽的,除了昨天在机房打游戏的某位朋友翻车后和教练谈了谈心2333
说题吧。。
1.BZOJ1208 HNOI2004 宠物收养所
这个题思路很简单,当做模板题打,在模板题中也算是简单的了,涉及操作:前驱,后继,插入,删除。。输入进来就插入,领养走就删除,并没有什么可说的。加上一个标记表示现在树上表示的是宠物还是人。
另外听说可以用set做,但是我并不会set(???set都不会吃屎吧)。
CODE:
#include<iostream>
#include<cstdio>
using namespace std;
int n,size,rt,kind,t1,t2;
long long ans;
int tr[][],num[],fa[];
void rotate(int x,int &k)
{
int y=fa[x],z=fa[y],l,r;
if(tr[y][]==x)l=;else l=;r=l^;
if(y==k)k=x;
else{if(tr[z][]==y)tr[z][]=x;else tr[z][]=x;}
fa[x]=z;fa[y]=x;fa[tr[x][r]]=y;
tr[y][l]=tr[x][r];tr[x][r]=y;
}
void splay(int x,int &k)
{
int y,z;
while(x!=k)
{
y=fa[x],z=fa[y];
if(y!=k)
{
if((tr[y][]==x)^(tr[z][]==y))rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
}
void ins(int &k,int x,int last)
{
if(k==){size++;k=size;num[k]=x;fa[k]=last;splay(k,rt);return;}
if(x<num[k])ins(tr[k][],x,k);else ins(tr[k][],x,k);
}
void del(int x)
{
splay(x,rt);
if(tr[x][]*tr[x][]==)
{rt=tr[x][]+tr[x][];}
else
{
int k=tr[x][];
while(tr[k][])k=tr[k][];
tr[k][]=tr[x][];fa[tr[x][]]=k;
rt=tr[x][];
}
fa[rt]=;
}
void ask_before(int k,int x)
{
if(k==)return;
if(num[k]<=x){t1=k;ask_before(tr[k][],x);}
else ask_before(tr[k][],x);
}
void ask_after(int k,int x)
{
if(k==)return;
if(num[k]>=x){t2=k;ask_after(tr[k][],x);}
else ask_after(tr[k][],x);
} int main()
{
scanf("%d",&n);
int f,x;
for(int i=;i<=n;i++)
{
scanf("%d%d",&f,&x);
if(!rt){kind=f;ins(rt,x,);}
else if(kind==f){ins(rt,x,);}
else
{
t1=t2=-;
ask_before(rt,x);ask_after(rt,x);
if(t1==-){ans+=num[t2]-x;ans%=;del(t2);}
else if(t2==-){ans+=x-num[t1];ans%=;del(t1);}
else
{
if(x-num[t1]>num[t2]-x) {ans+=num[t2]-x;ans%=;del(t2);}
else{ans+=x-num[t1];ans%=;del(t1);}
}
}
}
cout<<ans<<endl;
return ;
}
2.codevs1296 营业额统计
和前面一题类似,操作基本一样。
找出前驱后继,比较它们和当天营业额的差值,取小的那个给答案加上,完美。。
PS:前驱和后继初值赋值为正无穷或负无穷,以免找不到前驱/后继而成为 abs(0-当天营业额),影响答案取值。
CODE:
#include<bits/stdc++.h>
#define N 32769
using namespace std;
int c[N][],val[N],fa[N],tot,ans,n,rt,a,t1,t2;
int read(){
char c;int f=,x=;c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c<=''&&c>='')x=x*+c-'',c=getchar();
return f*x;
} void rotate(int x,int &k){
int y=fa[x],z=fa[y],l,r;
if(c[y][]==x)l=;else l=;r=l^;
if(y==k)k=x;
else c[z][c[z][]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
} void splay(int x,int &k){
while(x!=k){
int y=fa[x],z=fa[y];
if(y!=k){
if((c[y][]==x)^(c[z][]==y))rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
} void insert(int x){
if(!rt){
rt=++tot;
val[tot]=a;
return;
}
int p=rt,z;
while(p){
z=p;
if(a>=val[p])p=c[p][];
else p=c[p][];
}
if(a>=val[z])c[z][]=++tot;
else c[z][]=++tot;
val[tot]=a;fa[tot]=z;
splay(tot,rt);
} void ask_before(int x){
if(x==)return;
if(val[x]==a){t1=a;return;}
if(a>val[x]){t1=val[x];ask_before(c[x][]);}
else ask_before(c[x][]);
} void ask_after(int x){
if(x==)return;
if(val[x]==a){t2=a;return;}
if(a<val[x]){t2=val[x];ask_after(c[x][]);}
else ask_after(c[x][]);
} int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
a=read();
t1=t2=;
ask_before(rt);ask_after(rt);
if(i==)ans+=a;
else ans+=min(abs(t1-a),abs(t2-a));
insert(rt);
}
printf("%d",ans);
return ;
}
3.codevs1286 NOI2004郁闷的营销员
大致思路:伸展树基本操作+巧妙的整体修改
原本以为使用区间操作,但发现可以把原有人的工资增减变为所有人(包括增减工资后加的人)的增减。只用记录一个all ,然后插入新成员时减去all的值就行。
PS:关于下面那个splay操作,其实是可有可无的,只是优化了时间而已。若是懒,可以不打splay和rotate,BZOJ时间限制5s,一样可以水过,但codevs时间限制1s,要TLE几组
至于splay优化时间的原因:如果构成了一条长链(超级长,可近似看做一个O(n)的序列),通过splay可以把它的深度减小,变为一棵二叉树
CODE:
#include<bits/stdc++.h>
#define N 32769
using namespace std;
int c[N][],val[N],fa[N],tot,ans,n,rt,a,t1,t2;
int read(){
char c;int f=,x=;c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c<=''&&c>='')x=x*+c-'',c=getchar();
return f*x;
} void rotate(int x,int &k){
int y=fa[x],z=fa[y],l,r;
if(c[y][]==x)l=;else l=;r=l^;
if(y==k)k=x;
else c[z][c[z][]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
} void splay(int x,int &k){
while(x!=k){
int y=fa[x],z=fa[y];
if(y!=k){
if((c[y][]==x)^(c[z][]==y))rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
} void insert(int x){
if(!rt){
rt=++tot;
val[tot]=a;
return;
}
int p=rt,z;
while(p){
z=p;
if(a>=val[p])p=c[p][];
else p=c[p][];
}
if(a>=val[z])c[z][]=++tot;
else c[z][]=++tot;
val[tot]=a;fa[tot]=z;
splay(tot,rt);
} void ask_before(int x){
if(x==)return;
if(val[x]==a){t1=a;return;}
if(a>val[x]){t1=val[x];ask_before(c[x][]);}
else ask_before(c[x][]);
} void ask_after(int x){
if(x==)return;
if(val[x]==a){t2=a;return;}
if(a<val[x]){t2=val[x];ask_after(c[x][]);}
else ask_after(c[x][]);
} int main(){
scanf("%d",&n);
for(int i=;i<=n;i++){
a=read();
t1=t2=;
ask_before(rt);ask_after(rt);
if(i==)ans+=a;
else ans+=min(abs(t1-a),abs(t2-a));
insert(rt);
}
printf("%d",ans);
return ;
}
4.codevs3303 翻转区间
就是一个模板题啊,多次翻转区间,加上lazy标记就好
CODE:
#include<bits/stdc++.h>
#define N 100005
using namespace std;
int c[N][],fa[N],a[N],size[N],rev[N],rt,n,m;
int read(){
char c;int f=,x=;c=getchar();
while(c>''||c<''){if(c=='-')f=-;c=getchar();}
while(c<=''&&c>='')x=x*+c-'',c=getchar();
return f*x;
} void update(int x){
int l=c[x][],r=c[x][];
size[x]=size[l]+size[r]+;
} void pushdown(int x){
if(rev[x]){
swap(c[x][],c[x][]);rev[x]=;
rev[c[x][]]^=;rev[c[x][]]^=;
}
} void rotate(int x,int &k){
int y=fa[x],z=fa[y],l,r;
if(c[y][]==x)l=;else l=;r=l^;
if(y==k)k=x;
else c[z][c[z][]==y]=x;
fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
c[y][l]=c[x][r];c[x][r]=y;
update(y);update(x);
} void splay(int x,int &k){
while(x!=k){
int y=fa[x],z=fa[y];
if(y!=k){
if(c[y][]==x^c[z][]==y)rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
} void build(int l,int r,int f){
if(l>r)return;
if(l==r){
size[l]=;fa[l]=f;
if(l>f)c[f][]=l;
else c[f][]=l;
return;
}
int mid=(l+r)>>;
build(l,mid-,mid);build(mid+,r,mid);
update(mid);fa[mid]=f;c[f][mid>f]=mid;
} int find(int x,int k){
pushdown(x);
int l=c[x][],r=c[x][];
if(size[l]+==k)return x;
if(size[l]+>k)return find(l,k);
return find(r,k--size[l]);
} int main(){
n=read();m=read();
for(int i=;i<=n+;i++)a[i]=i;
build(,n+,);rt=(+n)>>;
int x,y;
for(int i=;i<=m;i++){
x=read(),y=read();
int l=find(rt,x),r=find(rt,y+);
splay(l,rt);splay(r,c[l][]);
rev[c[r][]]^=;
}
for(int i=;i<=n+;i++)
printf("%d ",find(rt,i)-); return ;
}
5.NOI2005 维修数列
就是那道恶心的题,今天磨了好久,终于自己打出来了,代码就不贴了,恶心恶心。。
在晚上8:30时,教练硬是把我们拖出去讲了manacher,很简单。。。30min讲完大家都懂了,代码超级短,也是不想多说什么。
愉快的一天终于结束了,基本掌握伸展树,可以的,回去写英语阅读了!
【集训第三天·疯狂训练】哦,顺带学习了manacher的更多相关文章
- WC2018集训 吉老师的军训练
WC2018集训 吉老师的军训练 #include<bits/stdc++.h> #define RG register #define IL inline #define _ 20000 ...
- Matlab中常见的神经网络训练函数和学习函数
一.训练函数 1.traingd Name:Gradient descent backpropagation (梯度下降反向传播算法 ) Description:triangd is a networ ...
- 第三次随笔--安装虚拟机及学习linux系统初体验
第三次随笔--安装虚拟机及学习linux系统初体验 ·学习基于VirtualBox虚拟机安装Ubuntu图文教程在自己笔记本上安装Linux操作系统 首先按照老师的提示步骤进行VirtualBox虚拟 ...
- 路飞学城-Python爬虫集训-第三章
这个爬虫集训课第三章的作业讲得是Scrapy 课程主要是使用Scrapy + Redis实现分布式爬虫 惯例贴一下作业: Python爬虫可以使用Requests库来进行简单爬虫的编写,但是Reque ...
- rnn实现三位数加法的训练
#!/usr/bin/env python # coding=utf-8 from keras.models import Sequential from keras.layers import Ac ...
- TensorFlow多线程输入数据处理框架(三)——组合训练数据
参考书 <TensorFlow:实战Google深度学习框架>(第2版) 通过TensorFlow提供的tf.train.batch和tf.train.shuffle_batch函数来将单 ...
- 谷歌BERT预训练源码解析(三):训练过程
目录前言源码解析主函数自定义模型遮蔽词预测下一句预测规范化数据集前言本部分介绍BERT训练过程,BERT模型训练过程是在自己的TPU上进行的,这部分我没做过研究所以不做深入探讨.BERT针对两个任务同 ...
- Contest1692 - 2019寒假集训第三十一场 UPC 11075 Problem D 小P的国际象棋
非常简单的单点修改+区间加+区间查询.我用的是最近刚学的区间修改版本树状数组. 直接维护即可,注意修改后的单点值已经不是a[i],或者b[i],要通过区间查询求单点.不然是错的. 区间修改版本树状数 ...
- ACM暑假集训第三周小结
这一周学的图论,学了这么些 两种存图的方法:邻接矩阵( map[n][n] ) , 邻接表( headlis[n] , vector<int> G[n] )存图的方法,各有各的好,我的理解 ...
随机推荐
- Java语言基础组成
写完才发现,这个博客不提供目录这个功能,真是想骂爹了...... 目录 关键字 标识符 注释 常量和变量 运算符 语句 函数 数组 1.关键字 描述:刚刚开始学这个的时候,真是傻傻分不清楚,不过没关系 ...
- EasyUI Datagrid 分页的情况下实现点击表头的小三角图标对数据库中所有数据重新排序
说明一下: 当点击 datagrid 表头某一列的小三角图标时,easyui 本身是有排序的,但是在当我们对 datagrid 进行了分页的情况下,点击排序只是对当前页的数据进行排序,而需求需要我对数 ...
- JS实现页面内跳转
使用js($.ajax中)实现页面内跳转(即:描点平滑跳转)的方法(aa为跳转目的标签的id): 在网络上有很多资料所说的:animate方法我试了并不好使,不知道是啥原因,欢迎大家指正,附上网络方法 ...
- 第5章 子网划分和CIDR
第5章 子网划分和CIDR 划分网络 根据A类.B类或C类网络ID来识别网段具有一些局限性,主要是在网络级别之下不能对地址空间进行任何逻辑细分 如果一个IP是一个A类网络.数据报到达网关,然后传输到9 ...
- Python内置函数(13)——bytearray
英文文档: class bytearray([source[, encoding[, errors]]]) Return a new array of bytes. The bytearray cla ...
- python 字符串的方法
capitalize() 把字符串的第一个字符改为大写 casefold() 把整个字符串的所有字符改为小写 center(width) 将字符串居中,并使用空格填充至长度 width 的新字符串 c ...
- Django之views系统
Django的View(视图)简介 一个视图函数(类),简称视图,是一个简单的Python 函数(类),它接受Web请求并且返回Web响应. 响应可以是一张网页的HTML内容,一个重定向,一个404错 ...
- final类与final方法
inal---用于类.方法前. final类---不可被继承. final方法---不可被覆盖. final类不能被继承. 如果我们不希望一个类被继承,我们使用final来修饰这个类.这个类将无法被继 ...
- python当中的生成器
最近身边的朋友都在问我迭代器是什么回事,经常跟大家一起讨论python的迭代器,一点点的我觉着自己有了更深一层的理解.我写下这篇文章,希望能对懵懵懂懂的好伙伴有些帮助~ 我也不是什么能人,难免说错一些 ...
- [机器学习实战]K-近邻算法
1. K-近邻算法概述(k-Nearest Neighbor,KNN) K-近邻算法采用测量不同的特征值之间的距离方法进行分类.该方法的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近 ...