【集训第四天·继续刷题】之 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 }

  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 }  

  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 }

  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 }

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

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

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

      chair-man tree

  

  

时间: 2024-10-10 04:46:31

【集训第四天·继续刷题】之 lgh怒刚ypj的相关文章

COGS2642 / Bzoj4590 [Shoi2015]自动刷题机

Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 906  Solved: 321 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序,每秒,自动刷题机的代码生成模 块会有两种可能的结果: A.写了x行代码. B.心情不好,删掉了之前写的y行代码.(如果y大于当前代码长度则相当于全部删除.) 对于每

BZOJ 4590: [Shoi2015]自动刷题机 二分答案

4590: [Shoi2015]自动刷题机 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1056  Solved: 380[Submit][Status][Discuss] Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序,每秒,自动刷题机的代码生成模 块会有两种可能的结果: A.写了x行代

BZOJ4590 自动刷题机

SHOI2015 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序,每秒,自动刷题机的代码生成模 块会有两种可能的结果: A.写了x行代码. B.心情不好,删掉了之前写的y行代码.(如果y大于当前代码长度则相当于全部删除.) 对于每个OJ所有题目,存在某个固定的长度n>0.一旦自动刷题机在某秒结束时积累了大于等于n行的代码,它就会 自动提交并

bzoj4590自动刷题机

传送门 Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写程序,每秒,自动刷题机的代码生成模 块会有两种可能的结果: A.写了x行代码. B.心情不好,删掉了之前写的y行代码.(如果y大于当前代码长度则相当于全部删除.) 对于每个OJ所有题目,存在某个固定的长度n>0.一旦自动刷题机在某秒结束时积累了大于等于n行的代码,它就会 自动提交并AC此题,

CSP-S集训刷题记录

$ CSP.S $ 集训刷题记录: $ By~wcwcwch $ 一.字符串专题: 1. [模板]$ manacher $ 算法 模型:求出字符串 $ S $ 中所有回文串的位置及长度. 个人理解:解决这类问题,回文串的对称性质最重要. 于复杂度最关键的一句话: $ f[i]=min~(~r-i~,~f[~mid\times2-i~]~)~ $ (实现不同,边界可能不一样) 这个 $ min $ 函数左边 $ r-i $ 是当前位置到它所属于的回文串边界的距离,右边 $ mid\times 2

刷题之路第四题--取两个顺序数组的数值的中位数

Median of Two Sorted Arrays 简介:取两个顺序数组的数值的中位数 问题详解: 给定两个排序的数组nums1和nums2分别为m和n,我们需要的是两个数组中所组成一个数列的中位数. 注意: 1.需要判断数组NPE 2.结果不是int 举例 1: nums1 = [1, 3] nums2 = [2] 中位数是 2.0 2: nums1 = [1, 2] nums2 = [3, 4] 中位数是 (2 + 3)/2 = 2.5 JAVA 实现方法一: 通过NPE判断后将两个数组

7、8月刷题总结

准备开学了囧,7.8月刷题记录,以后好来复习,并且还要好好总结! 数据结构: splay: [BZOJ]1503: [NOI2004]郁闷的出纳员(Splay) [BZOJ]1269: [AHOI2006]文本编辑器editor(Splay) [BZOJ]1507: [NOI2003]Editor(Splay) treap: [BZOJ]1862: [Zjoi2006]GameZ游戏排名系统 & 1056: [HAOI2008]排名系统(treap+非常小心) [BZOJ]3224: Tyvj

【leetcode刷题笔记】Restore IP Addresses

Given a string containing only digits, restore it by returning all possible valid IP address combinations. For example:Given "25525511135", return ["255.255.11.135", "255.255.111.35"]. (Order does not matter) 题解:深度优先搜索.用resul

【leetcode刷题笔记】Spiral Matrix II

Given an integer n, generate a square matrix filled with elements from 1 to n2 in spiral order. For example,Given n = 3, You should return the following matrix: [ [ 1, 2, 3 ], [ 8, 9, 4 ], [ 7, 6, 5 ] ] 题解:以前做过的Spiral Matrix是给一个矩阵螺旋式的输出,这道题是给一个n,螺旋式的