集训第四天·继续刷题之 lgh怒刚ypj

Posted wsy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了集训第四天·继续刷题之 lgh怒刚ypj相关的知识,希望对你有一定的参考价值。

  继续水题,终于完全掌握了伸展树了,好心痛QAQ。

  1.codevs1343 蚱蜢

  区间最大值查询+单点移动

  最大值查询维护一个mx数组就行,单点移动么,先删除在插入

CODE:

技术分享
 1 /*
 2 PS:  比较max值时,要写成 mx[x]=max(a[x],max(mx[l],mx[r]));形式 
 3     且最好把mx[0]赋值为负无穷大
 4     
 5 取max时,注意初值问题 
 6 
 7 */
 8 
 9 #include<bits/stdc++.h>
10 #define N 100005
11 using namespace std;
12 int c[N][2],fa[N],a[N],size[N],mx[N],n,m,rt;
13 int read(){
14     char c;int f=1,x=0;c=getchar();
15     while(c>9||c<0){if(c==-)f=-1;c=getchar();}
16     while(c<=9&&c>=0)x=x*10+c-0,c=getchar();
17     return f*x;
18 }
19 
20 void pushup(int x){
21     int l=c[x][0],r=c[x][1];
22     size[x]=size[l]+size[r]+1;
23     mx[x]=max(a[x],max(mx[l],mx[r]));
24 }
25 
26 void rotate(int x,int &k){//旋转
27     int y=fa[x],z=fa[y],l,r;
28     l=(c[y][1]==x);r=l^1;
29     if(y==k)k=x;
30     else c[z][c[z][1]==y]=x;
31     fa[c[x][r]]=y;fa[y]=x;fa[x]=z;
32     c[y][l]=c[x][r];c[x][r]=y;
33     pushup(y);pushup(x);
34 }
35 
36 void splay(int x,int &k){//转化为根
37     while(x!=k){
38         int y=fa[x],z=fa[y];
39         if(y!=k){
40             if(c[y][0]==x^c[z][0]==y)rotate(x,k);
41             else rotate(y,k);
42         }
43         rotate(x,k);
44     }
45 }
46 
47 void build(int l,int r,int f){
48     if(l>r)return;
49     if(l==r){c[f][l>=f]=l;fa[l]=f;mx[l]=a[l];size[l]=1;return;}
50     int mid=(l+r)>>1;build(l,mid-1,mid);build(mid+1,r,mid);
51     pushup(mid);fa[mid]=f;c[f][mid>=f]=mid;
52 }
53 
54 int find(int x,int k){
55     int l=c[x][0],r=c[x][1];
56     if(size[l]+1==k)return x;
57     if(size[l]>=k)return find(l,k);
58     return find(r,k-size[l]-1);
59 }
60 
61 void query(int l,int r){
62     int x=find(rt,l),y=find(rt,r+2);
63     splay(x,rt);splay(y,c[x][1]);
64     printf("%d\n",mx[c[y][0]]);
65 }
66 
67 void move(int l,int r){
68     int x=find(rt,l),y=find(rt,l+2);
69     splay(x,rt);splay(y,c[x][1]);
70     int now=c[y][0];fa[now]=0;
71     c[y][0]=0;pushup(y);pushup(x);
72     x=find(rt,r+1);y=find(rt,r+2);
73     splay(x,rt);splay(y,c[x][1]);
74     c[y][0]=now;fa[now]=y;
75     pushup(y);pushup(x);
76 }
77 
78 int main(){
79     n=read();m=read();
80     a[1]=a[n+2]=-99999999;
81     for(int i=1;i<=n;i++)a[i+1]=read();
82     build(1,n+2,0);rt=(n+3)>>1;
83     while(m--){
84         printf("\n");
85         int l,r;char s[10];l=read();
86         scanf("%s",s);
87         if(s[0]==D){r=read()+l;query(l+1,r);move(l,r-1);}
88         else{r=l-read();query(r,l-1);move(l,r-1);}
89     /*    for(int i=2;i<=n+1;i++){
90             int dada=find(rt,i);
91             printf("%d ",a[dada]);
92         }*/
93     }
94     return 0;
95 }
View Code

 

  2.codevs1514 书架

  单点移动+单点查询

  移动还是一样,先删除再插入

  查询编号为S的书的上面目前有多少本书时,把S调整至根节点,输出左边儿子的元素个数即可

  查询从上面数起的第S本书的编号,find(S)即可。

CODE:

技术分享
 1 #include<cstdio>  
 2 #include<cstring>  
 3 using namespace std;  
 4   
 5 const int INF = 1e9 + 7;  
 6 const int maxn = 80000 + 10;  
 7   
 8 int n, m, root;  
 9 int ch[maxn][2], p[maxn], a[maxn], s[maxn], v[maxn], id[maxn];  
10   
11 void update(int k) {  
12     s[k] = s[ch[k][0]] + s[ch[k][1]] + 1;   
13 }  
14   
15 void rotate(int& px, int& x, int d) {  
16     int t = ch[x][d]; ch[x][d] = px; ch[px][d^1] = t;   
17     p[x] = p[px]; p[px] = x; p[t] = px; update(px); update(x); px = x;  
18 }  
19   
20 void splay(int x, int& k) {  
21     while(x != k) {  
22         int y = p[x], z = p[y];  
23         int d = ch[y][0] == x ? 0 : 1;  
24         int d2 = ch[z][0] == y ? 0 : 1;  
25         if(y != k) rotate(ch[z][d2], x, d^1); else rotate(k, x, d^1);  
26     }  
27 }  
28   
29 void build(int L, int R, int P, int d) {  
30     if(L == R) { s[L] = 1; p[L] = P; ch[P][d] = L; return; }  
31     int M = (L+R) >> 1;  
32     p[M] = P; ch[P][d] = M;  
33     if(M-1 >= L) build(L, M-1, M, 0);   
34     if(R >= M+1) build(M+1, R, M, 1);  
35     update(M);  
36 }  
37   
38 int find(int k, int rank) {  
39     int l = ch[k][0], r = ch[k][1];   
40     if(s[l]+1 == rank) return k;   
41     else if(s[l] >= rank) return find(l, rank);   
42     else return find(r, rank-s[l]-1);   
43 }  
44   
45 void remove(int k) {  
46     int x, y, z;   
47     x = find(root, k-1); y = find(root, k+1);   
48     splay(x, root); splay(y, ch[x][1]);   
49     z = ch[y][0]; ch[y][0] = 0; p[z] = s[z] = 0;   
50     update(y); update(x);   
51 }  
52   
53 void move(int k, int val)  {  
54     int o = id[k], x, y, rank;  
55     splay(o, root);   
56     rank = s[ch[o][0]] + 1;   
57     remove(rank);   
58     if(val == INF) x = find(root, n), y = find(root, n+1);   
59     else if(val == -INF) x = find(root, 1), y = find(root, 2);   
60     else x = find(root, rank+val-1), y = find(root, rank+val);   
61     splay(x, root); splay(y, ch[x][1]);   
62     s[o] = 1; p[o] = y; ch[y][0] = o;   
63     update(y); update(x);   
64 }  
65   
66 int main() {  
67     scanf("%d%d", &n, &m);  
68     for(int i = 2; i <= n+1; i++) scanf("%d", &v[i]), id[v[i]] = i;   
69     build(1, n+2, 0, 1);   
70     root = (n+3) >> 1;   
71       
72     char cmd[10]; int S, T;   
73     for(int i = 1; i <= m; i++) {  
74         scanf("%s%d", cmd, &S);   
75         switch(cmd[0]) {  
76             case T: move(S, -INF); break;   
77             case B: move(S, INF); break;   
78             case I: scanf("%d", &T); move(S, T); break;   
79             case A: splay(id[S], root); printf("%d\n", s[ch[id[S]][0]]-1); break;   
80             case Q: printf("%d\n", v[find(root, S+1)]); break;   
81         }  
82     }  
83     return 0;   
84 }  
View Code

 

  3.codevs1743 反转卡片

  简单到爆,一直区间倒置直到第一个数==1为止

CODE:

技术分享
 1 #include<bits/stdc++.h>
 2 #define N 300005
 3 using namespace std;
 4 int c[N][2],fa[N],a[N],v[N],size[N],rev[N],rt,n,m;
 5 int read(){
 6     char c;int f=1,x=0;c=getchar();
 7     while(c>9||c<0){if(c==-)f=-1;c=getchar();}
 8     while(c<=9&&c>=0)x=x*10+c-0,c=getchar();
 9     return f*x;
10 }
11 
12 void update(int x){
13     int l=c[x][0],r=c[x][1];
14     size[x]=size[l]+size[r]+1;
15 }
16 
17 void pushdown(int x){
18     if(rev[x]){
19         swap(c[x][0],c[x][1]);rev[x]=0;
20         if(c[x][0])rev[c[x][0]]^=1;
21         if(c[x][1])rev[c[x][1]]^=1;
22     }
23 }
24 
25 void rotate(int x,int &k){
26     int y=fa[x],z=fa[y],l,r;
27     if(c[y][0]==x)l=0;else l=1;r=l^1;
28     if(y==k)k=x;
29     else c[z][c[z][1]==y]=x;
30     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
31     c[y][l]=c[x][r];c[x][r]=y;
32     update(y);update(x);
33 }
34 
35 void splay(int x,int &k){
36     while(x!=k){
37         int y=fa[x],z=fa[y];
38         if(y!=k){
39             if(c[y][0]==x^c[z][0]==y)rotate(x,k);
40             else rotate(y,k);
41         }
42         rotate(x,k);
43     }
44 }
45 
46 void build(int l,int r,int f){
47     if(l>r)return;
48     if(l==r){
49         size[l]=1;fa[l]=f;
50         if(l>f)c[f][1]=l;
51         else c[f][0]=l;
52         v[l]=a[l];
53         return;
54     }
55     int mid=(l+r)>>1;v[mid]=a[mid];
56     build(l,mid-1,mid);build(mid+1,r,mid);
57     update(mid);fa[mid]=f;c[f][mid>f]=mid;
58 }
59 
60 int find(int x,int k){
61     pushdown(x);
62     int l=c[x][0],r=c[x][1];
63     if(size[l]+1==k)return x;
64     if(size[l]+1>k)return find(l,k);
65     return find(r,k-1-size[l]);
66 }
67 
68 void rever(int l,int r){
69     int x=find(rt,l),y=find(rt,r+2);
70     splay(x,rt);splay(y,c[x][1]);
71     rev[c[y][0]]^=1;
72 }
73 
74 int main(){
75     n=read();
76     a[0]=a[n+2]=99999999;
77     for(int i=1;i<=n;i++)a[i+1]=read();
78     build(1,n+2,0);rt=(3+n)>>1;
79      int x,y,ans=0;
80     while(1){
81         y=find(rt,2);
82         x=v[y];
83         if(x==1||ans>100000)break;
84         else rever(1,x);
85         ans++;
86     }
87     printf("%d",ans>100000?-1:ans);
88     return 0;
89 }
View Code

 

  4.codevs1985 GameZ游戏排名系统

  cnm劳资这个题调了一个晚上。。。。泪流满面,本来还可以多写2个题的。

  使用hash或者map建立映射,记录某人是否已出现,如果出现的话删除再插入,否则直接插入

  查询玩家排名时,直接查询他的编号,把编号调整至根节点,输出右边儿子的元素个数

  最坑比的就是输出从第x位起排名前10位的人。。我先用的是查找函数,直接查找排名第x+1,x+2……点的编号并输出名字,然而效率及其低下,codevsTLE3组。后来美腻的张姐告诉我:把x~x+10区间调整至一个子树上,然后中序遍历,输出。我TM真的是个智障。。

  PS:注意建立两个虚节点分别作为第一和倒数第一,来保证splay操作的正确性或者加上特殊的判断处理,但特判有些麻烦

CODE:

技术分享
  1 //愚蠢的TLE :输出一段连续的区间值时,不要一个一个找每个数的位置(超级费时间)
  2 //                                   把那整个区间转移到一棵子树上,中序输出 
  3 #include<bits/stdc++.h>
  4 #define N 250005
  5 #define inf 2147483647
  6 using namespace std;
  7 int n,c[N][2],fa[N],val[N],size[N],tot,rt,t1,t2;
  8 char s[15];
  9 struct player{
 10     int sc;
 11     char na[15];
 12 }p[N];
 13 map<string,int>mp;
 14 int read(){
 15     char c;int f=1,x=0;c=getchar();
 16     while(c>9||c<0){if(c==-)f=-1;c=getchar();}
 17     while(c<=9&&c>=0)x=x*10+c-0,c=getchar();
 18     return f*x;
 19 }
 20 
 21 void pushup(int x){
 22     int l=c[x][0],r=c[x][1];
 23     size[x]=size[l]+size[r]+1;
 24 }
 25 
 26 void rotate(int x,int &k){
 27     int y=fa[x],z=fa[y],l,r;
 28     if(c[y][0]==x)l=0;else l=1;r=l^1;
 29     if(y==k)k=x;
 30     else c[z][c[z][1]==y]=x;
 31     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
 32     c[y][l]=c[x][r];c[x][r]=y;
 33     pushup(y);pushup(x);
 34 }
 35 
 36 void splay(int x,int &k){
 37     while(x!=k){
 38         int y=fa[x],z=fa[y];
 39         if(y!=k){
 40             if((c[y][0]==x)^(c[z][0]==y))rotate(x,k);
 41             else rotate(y,k);
 42         }
 43         rotate(x,k);
 44     }
 45 }
 46 
 47 void insert(int v,int num){
 48     if(!rt){rt=num;val[num]=v;size[rt]=1;return;}
 49     int p=rt,z;
 50     while(p){
 51         size[p]++;z=p;
 52         if(val[p]<v)p=c[p][1];
 53         else p=c[p][0];
 54     }
 55     val[num]=v;c[z][v>val[z]]=num;
 56     fa[num]=z;size[num]=1;
 57     splay(num,rt);
 58 }
 59 
 60 int find(int x,int k){
 61     int l=c[x][0],r=c[x][1];
 62     if(size[r]+1==k)return x;
 63     if(size[r]>=k)return find(r,k);
 64     return find(l,k-size[r]-1);
 65 }
 66 
 67 int trans(){
 68     int i=0,x=0;
 69     while(s[i]){x=x*10+s[i]-0;i++;}
 70     return x;
 71 }
 72 
 73 void del(int x){
 74     splay(x,rt);
 75     int l=c[x][0],r=c[x][1];
 76     while(c[l][1])l=c[l][1];
 77     while(c[r][0])r=c[r][0];
 78     splay(l,rt);splay(r,c[l][1]);
 79     fa[c[r][0]]=0;c[r][0]=0;
 80     pushup(r);pushup(l);
 81 }
 82 
 83 void print(int x){
 84     if(!x)return;
 85     print(c[x][1]);
 86     printf("%s ",p[x].na);
 87     print(c[x][0]);
 88 }
 89 
 90 void find_name(int a){
 91     int b=min(a+11,tot);
 92     int x=find(rt,b),y=find(rt,a);
 93     splay(x,rt);splay(y,c[x][1]);
 94     pushup(y);pushup(x);
 95     print(c[y][0]);
 96     printf("\n");
 97 }
 98 
 99 int main(){
100     n=read();
101     insert(inf,1);
102     insert(-1,2);
103     tot=2;
104     for(int i=1;i<=n;i++){
105         char ch;scanf(" %c",&ch);
106         if(ch==+){
107             scanf("%s",p[++tot].na);p[tot].sc=read();
108             if(mp[p[tot].na]){
109                 int ps=mp[p[tot].na];
110                 del(ps);
111                 p[ps].sc=p[tot].sc;
112                 insert(p[tot].sc,ps);
113                 tot--;
114             }
115             else {
116                 mp[p[tot].na]=tot;
117                 insert(p[tot].sc,tot);
118             }
119         }
120         else {
121             scanf("%s",s);
122             if(s[0]>=1&&s[0]<=9){
123                 int pos=trans();
124                 find_name(pos);
125             }
126             else{
127                 int ps=mp[s];
128                 splay(ps,rt);
129                 printf("%d\n",size[c[rt][1]]);
130             }
131         }
132         
133     }
134     return 0;
135 }
View Code

 

 

  记录一件事情,今晚lgh和ypj吵架了,原因是我们想离开高二机房,他不准,lgh又不肯退步,于是造成了惨剧(开玩笑)。。后来ypj就一直教育他(期间再次提到了某位打游戏翻车的同学),搞得他心情很不好啊,于是他就开始挤兑ypj,我估计后来ypj也非常不高兴。

  其实这件事呢,我们是不占理的。首先是没给ypj说一声就想走,十分的不尊重,其二就是lgh可能被愤怒冲昏了头脑,说话非常的冲,让人听了很不爽,交流方式确实有些问题。当然ypj说话也有些问题,他非常的不善言辞(就是瞎几把说话)。在我看来,和ypj吵并不值得,因为他本来就很不可理喻,思想跟我们完全脱节。以后遇到这种情况,我们最好就是不跟他说屁话,打代码。他bb够了自己就离开了,免得吵起来双方都不爽。

 

  今天ypj讲了主席树,我听懂了思想,但具体代码实现还有些懵逼,明天再看看。。

      chair-man tree

 

 

  

  


以上是关于集训第四天·继续刷题之 lgh怒刚ypj的主要内容,如果未能解决你的问题,请参考以下文章

蓝桥集训(附加面试题)第四天

Java集训(算法&&面试题)第四天 (链表 & 树)

暑期集训第四天(6-25)题解及总结

《九日集训 - 雪国列车》(第四天) 一维数组(leetcode零基础打卡指南)

LeetCode刷题之搜索(Java)

LeetCode刷题之搜索(Java)