【集训第四天·继续刷题】之 lgh怒刚ypj
继续水题,终于完全掌握了伸展树了,好心痛QAQ。
1.codevs1343 蚱蜢
区间最大值查询+单点移动
最大值查询维护一个mx数组就行,单点移动么,先删除在插入
CODE:
/*
PS: 比较max值时,要写成 mx[x]=max(a[x],max(mx[l],mx[r]));形式
且最好把mx[0]赋值为负无穷大 取max时,注意初值问题 */ #include<bits/stdc++.h>
#define N 100005
using namespace std;
int c[N][],fa[N],a[N],size[N],mx[N],n,m,rt;
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 pushup(int x){
int l=c[x][],r=c[x][];
size[x]=size[l]+size[r]+;
mx[x]=max(a[x],max(mx[l],mx[r]));
} void rotate(int x,int &k){//旋转
int y=fa[x],z=fa[y],l,r;
l=(c[y][]==x);r=l^;
if(y==k)k=x;
else c[z][c[z][]==y]=x;
fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
c[y][l]=c[x][r];c[x][r]=y;
pushup(y);pushup(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){c[f][l>=f]=l;fa[l]=f;mx[l]=a[l];size[l]=;return;}
int mid=(l+r)>>;build(l,mid-,mid);build(mid+,r,mid);
pushup(mid);fa[mid]=f;c[f][mid>=f]=mid;
} int find(int x,int k){
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]-);
} void query(int l,int r){
int x=find(rt,l),y=find(rt,r+);
splay(x,rt);splay(y,c[x][]);
printf("%d\n",mx[c[y][]]);
} void move(int l,int r){
int x=find(rt,l),y=find(rt,l+);
splay(x,rt);splay(y,c[x][]);
int now=c[y][];fa[now]=;
c[y][]=;pushup(y);pushup(x);
x=find(rt,r+);y=find(rt,r+);
splay(x,rt);splay(y,c[x][]);
c[y][]=now;fa[now]=y;
pushup(y);pushup(x);
} int main(){
n=read();m=read();
a[]=a[n+]=-;
for(int i=;i<=n;i++)a[i+]=read();
build(,n+,);rt=(n+)>>;
while(m--){
printf("\n");
int l,r;char s[];l=read();
scanf("%s",s);
if(s[]=='D'){r=read()+l;query(l+,r);move(l,r-);}
else{r=l-read();query(r,l-);move(l,r-);}
/* for(int i=2;i<=n+1;i++){
int dada=find(rt,i);
printf("%d ",a[dada]);
}*/
}
return ;
}
2.codevs1514 书架
单点移动+单点查询
移动还是一样,先删除再插入
查询编号为S的书的上面目前有多少本书时,把S调整至根节点,输出左边儿子的元素个数即可
查询从上面数起的第S本书的编号,find(S)即可。
CODE:
#include<cstdio>
#include<cstring>
using namespace std; const int INF = 1e9 + ;
const int maxn = + ; int n, m, root;
int ch[maxn][], p[maxn], a[maxn], s[maxn], v[maxn], id[maxn]; void update(int k) {
s[k] = s[ch[k][]] + s[ch[k][]] + ;
} void rotate(int& px, int& x, int d) {
int t = ch[x][d]; ch[x][d] = px; ch[px][d^] = t;
p[x] = p[px]; p[px] = x; p[t] = px; update(px); update(x); px = x;
} void splay(int x, int& k) {
while(x != k) {
int y = p[x], z = p[y];
int d = ch[y][] == x ? : ;
int d2 = ch[z][] == y ? : ;
if(y != k) rotate(ch[z][d2], x, d^); else rotate(k, x, d^);
}
} void build(int L, int R, int P, int d) {
if(L == R) { s[L] = ; p[L] = P; ch[P][d] = L; return; }
int M = (L+R) >> ;
p[M] = P; ch[P][d] = M;
if(M- >= L) build(L, M-, M, );
if(R >= M+) build(M+, R, M, );
update(M);
} int find(int k, int rank) {
int l = ch[k][], r = ch[k][];
if(s[l]+ == rank) return k;
else if(s[l] >= rank) return find(l, rank);
else return find(r, rank-s[l]-);
} void remove(int k) {
int x, y, z;
x = find(root, k-); y = find(root, k+);
splay(x, root); splay(y, ch[x][]);
z = ch[y][]; ch[y][] = ; p[z] = s[z] = ;
update(y); update(x);
} void move(int k, int val) {
int o = id[k], x, y, rank;
splay(o, root);
rank = s[ch[o][]] + ;
remove(rank);
if(val == INF) x = find(root, n), y = find(root, n+);
else if(val == -INF) x = find(root, ), y = find(root, );
else x = find(root, rank+val-), y = find(root, rank+val);
splay(x, root); splay(y, ch[x][]);
s[o] = ; p[o] = y; ch[y][] = o;
update(y); update(x);
} int main() {
scanf("%d%d", &n, &m);
for(int i = ; i <= n+; i++) scanf("%d", &v[i]), id[v[i]] = i;
build(, n+, , );
root = (n+) >> ; char cmd[]; int S, T;
for(int i = ; i <= m; i++) {
scanf("%s%d", cmd, &S);
switch(cmd[]) {
case 'T': move(S, -INF); break;
case 'B': move(S, INF); break;
case 'I': scanf("%d", &T); move(S, T); break;
case 'A': splay(id[S], root); printf("%d\n", s[ch[id[S]][]]-); break;
case 'Q': printf("%d\n", v[find(root, S+)]); break;
}
}
return ;
}
3.codevs1743 反转卡片
简单到爆,一直区间倒置直到第一个数==1为止
CODE:
#include<bits/stdc++.h>
#define N 300005
using namespace std;
int c[N][],fa[N],a[N],v[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]=;
if(c[x][])rev[c[x][]]^=;
if(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;
v[l]=a[l];
return;
}
int mid=(l+r)>>;v[mid]=a[mid];
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]);
} void rever(int l,int r){
int x=find(rt,l),y=find(rt,r+);
splay(x,rt);splay(y,c[x][]);
rev[c[y][]]^=;
} int main(){
n=read();
a[]=a[n+]=;
for(int i=;i<=n;i++)a[i+]=read();
build(,n+,);rt=(+n)>>;
int x,y,ans=;
while(){
y=find(rt,);
x=v[y];
if(x==||ans>)break;
else rever(,x);
ans++;
}
printf("%d",ans>?-:ans);
return ;
}
4.codevs1985 GameZ游戏排名系统
cnm劳资这个题调了一个晚上。。。。泪流满面,本来还可以多写2个题的。
使用hash或者map建立映射,记录某人是否已出现,如果出现的话删除再插入,否则直接插入
查询玩家排名时,直接查询他的编号,把编号调整至根节点,输出右边儿子的元素个数
最坑比的就是输出从第x位起排名前10位的人。。我先用的是查找函数,直接查找排名第x+1,x+2……点的编号并输出名字,然而效率及其低下,codevsTLE3组。后来美腻的张姐告诉我:把x~x+10区间调整至一个子树上,然后中序遍历,输出。我TM真的是个智障。。
PS:注意建立两个虚节点分别作为第一和倒数第一,来保证splay操作的正确性或者加上特殊的判断处理,但特判有些麻烦
CODE:
//愚蠢的TLE :输出一段连续的区间值时,不要一个一个找每个数的位置(超级费时间)
// 把那整个区间转移到一棵子树上,中序输出
#include<bits/stdc++.h>
#define N 250005
#define inf 2147483647
using namespace std;
int n,c[N][],fa[N],val[N],size[N],tot,rt,t1,t2;
char s[];
struct player{
int sc;
char na[];
}p[N];
map<string,int>mp;
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 pushup(int x){
int l=c[x][],r=c[x][];
size[x]=size[l]+size[r]+;
} 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;
pushup(y);pushup(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 insert(int v,int num){
if(!rt){rt=num;val[num]=v;size[rt]=;return;}
int p=rt,z;
while(p){
size[p]++;z=p;
if(val[p]<v)p=c[p][];
else p=c[p][];
}
val[num]=v;c[z][v>val[z]]=num;
fa[num]=z;size[num]=;
splay(num,rt);
} int find(int x,int k){
int l=c[x][],r=c[x][];
if(size[r]+==k)return x;
if(size[r]>=k)return find(r,k);
return find(l,k-size[r]-);
} int trans(){
int i=,x=;
while(s[i]){x=x*+s[i]-'';i++;}
return x;
} void del(int x){
splay(x,rt);
int l=c[x][],r=c[x][];
while(c[l][])l=c[l][];
while(c[r][])r=c[r][];
splay(l,rt);splay(r,c[l][]);
fa[c[r][]]=;c[r][]=;
pushup(r);pushup(l);
} void print(int x){
if(!x)return;
print(c[x][]);
printf("%s ",p[x].na);
print(c[x][]);
} void find_name(int a){
int b=min(a+,tot);
int x=find(rt,b),y=find(rt,a);
splay(x,rt);splay(y,c[x][]);
pushup(y);pushup(x);
print(c[y][]);
printf("\n");
} int main(){
n=read();
insert(inf,);
insert(-,);
tot=;
for(int i=;i<=n;i++){
char ch;scanf(" %c",&ch);
if(ch=='+'){
scanf("%s",p[++tot].na);p[tot].sc=read();
if(mp[p[tot].na]){
int ps=mp[p[tot].na];
del(ps);
p[ps].sc=p[tot].sc;
insert(p[tot].sc,ps);
tot--;
}
else {
mp[p[tot].na]=tot;
insert(p[tot].sc,tot);
}
}
else {
scanf("%s",s);
if(s[]>=''&&s[]<=''){
int pos=trans();
find_name(pos);
}
else{
int ps=mp[s];
splay(ps,rt);
printf("%d\n",size[c[rt][]]);
}
} }
return ;
}
记录一件事情,今晚lgh和ypj吵架了,原因是我们想离开高二机房,他不准,lgh又不肯退步,于是造成了惨剧(开玩笑)。。后来ypj就一直教育他(期间再次提到了某位打游戏翻车的同学),搞得他心情很不好啊,于是他就开始挤兑ypj,我估计后来ypj也非常不高兴。
其实这件事呢,我们是不占理的。首先是没给ypj说一声就想走,十分的不尊重,其二就是lgh可能被愤怒冲昏了头脑,说话非常的冲,让人听了很不爽,交流方式确实有些问题。当然ypj说话也有些问题,他非常的不善言辞(就是瞎几把说话)。在我看来,和ypj吵并不值得,因为他本来就很不可理喻,思想跟我们完全脱节。以后遇到这种情况,我们最好就是不跟他说屁话,打代码。他bb够了自己就离开了,免得吵起来双方都不爽。
今天ypj讲了主席树,我听懂了思想,但具体代码实现还有些懵逼,明天再看看。。
chair-man tree
【集训第四天·继续刷题】之 lgh怒刚ypj的更多相关文章
- 【BZOJ-4590】自动刷题机 二分 + 判定
4590: [Shoi2015]自动刷题机 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 156 Solved: 63[Submit][Status ...
- BZOJ4590 自动刷题机
Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写 ...
- BZOJ_4590_[Shoi2015]自动刷题机_二分答案
BZOJ_4590_[Shoi2015]自动刷题机_二分答案 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题 ...
- BZOJ4590 Shoi2015 自动刷题机 【二分】
BZOJ4590 Shoi2015 自动刷题机 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机–一种可以自动AC题目的神秘装置.自动刷题机刷题的方式非常简 ...
- 【BZOJ4590】[Shoi2015]自动刷题机 二分
[BZOJ4590][Shoi2015]自动刷题机 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动刷题机刷题的方式 ...
- COGS2642 / Bzoj4590 [Shoi2015]自动刷题机
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 906 Solved: 321 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了 ...
- LibreOJ #2036. 「SHOI2015」自动刷题机
#2036. 「SHOI2015」自动刷题机 内存限制:256 MiB时间限制:1000 ms标准输入输出 题目类型:传统评测方式:文本比较 题目描述 曾经发明了信号增幅仪的发明家 SHTSC 又公开 ...
- 「BZOJ4590」「SHOI2015」 自动刷题机 解题报告
自动刷题机 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法, ...
- ZJOI2019一轮停课刷题记录
Preface 菜鸡HL终于狗来了他的省选停课,这次的时间很长,暂定停到一试结束,不过有机会二试的话还是可以搞到4月了 这段时间的学习就变得量大而且杂了,一般以刷薄弱的知识点和补一些新的奇怪技巧为主. ...
随机推荐
- day-6 机器学习概念及应用
学习玩Python基础语法,今天开始进行机器学习,首先了解下机器学习和深度学习的一些基本概念和术语: 1. 机器学习概念及应用 2. 深度学习概念及应用 3. 机器学习基本术语及举例 4. 机 ...
- AngularJS1.X学习笔记7-过滤器
最近参加笔试被虐成狗了,感觉自己的算法太弱了.但是还是先花点事件将这个AngularJS学习完.今天学习filter 一.内置过滤器 (1)过滤单个数据值 <!DOCTYPE html> ...
- WPF 自定义TextBox带水印控件,可设置圆角
一.简单设置水印TextBox控件,废话不多说看代码: <TextBox TextWrapping="Wrap" Margin="10" Height=& ...
- Python Tornado初学笔记之表单与模板(一)
Tornado中的表单和HTML5中的表单具有相同的用途,同样是用于内容的填写.只是不同的是Tornado中的表单需要传入到后台,然后通过后台进行对模板填充. 模板:是一个允许嵌入Python代码片段 ...
- 初次面对c++
第一次实验 2-4源码: #include<iostream> using namespace std; int main() { int day; cin>>day; swi ...
- 九、Python+Selenium模拟用QQ登陆腾讯课堂,并提取报名课程(练习)
研究QQ登录规则的话,得分析大量Javascript的加密解密,比较耗时间.自己也是练习很少,短时间成功不了.所以走了个捷径. Selenium是一个WEB自动化测试工具,它运行时会直接实例化出一个浏 ...
- JsonCPP库使用
1.使用环境DevC++ a.建立C++工程,并添加.\JsonCPP\jsoncpp-master\jsoncpp-master\src\lib_json中源文件到工程中. b.添加头文件路径 2. ...
- 未能加载文件或程序集“ RevitAPIUI.dll”
revit二次开发中遇到的问题 RevitAPIUI.dll 只能 Native Library 中执行: 脱离了Native Library,API是跑不起来的 . 检查程序流程:登录,配置,启动r ...
- js、jQuery 获取文档、窗口、元素的各种值
基于两年开发经验,总结了 javascript.jQuery 获取窗口.文档.元素的各种值 javascript: 文档:是整个document所有的内容 浏览器当前窗口文档body的宽度: docu ...
- python虚拟环境--virtualenv
virtualenv 是一个创建隔绝的Python环境的工具.virtualenv创建一个包含所有必要的可执行文件的文件夹,用来使用Python工程所需的包. 安装 pip install virtu ...