hdu 4680 About set 小记(毕竟是一天的时光啊)
Problem Description
Today Zhanyl (sister Zhan as you know) receives a task about set operation. Although she is very good at this task,
but you know she is very lazy so that she wants you to help her write a program to complete this task. Surly
Zhanyl is able to solve this question, but you know, she is just lazy ...
Here is the problem, you are given n numbers, each number i has a value A i, initially they are in different set.
Following there are m operations/querys.
The following is 5 possible kinds of oprations/querys:
1 u v: Union the set u belongs to and the set v belongs to.
2 u v: Delete u from its original set and add it to the set v belongs to.
3 u x: change the value of u to x. 1<=x<=10 9
4 u: query how many numbers you can choose most in set which u belongs to, so no three numbers can form a triangle.
5 u l r: query the gcd of the numbers between [l,r] in the set u belongs to, if there is no number between [l,r],you can suppose the answer is -1. 1<=l<=r<=109
Because Zhanyl is a good person, so she guarantee 1<=u,v<=n above.
You need to tell Zhanyl the answer to each query.
but you know she is very lazy so that she wants you to help her write a program to complete this task. Surly
Zhanyl is able to solve this question, but you know, she is just lazy ...
Here is the problem, you are given n numbers, each number i has a value A i, initially they are in different set.
Following there are m operations/querys.
The following is 5 possible kinds of oprations/querys:
1 u v: Union the set u belongs to and the set v belongs to.
2 u v: Delete u from its original set and add it to the set v belongs to.
3 u x: change the value of u to x. 1<=x<=10 9
4 u: query how many numbers you can choose most in set which u belongs to, so no three numbers can form a triangle.
5 u l r: query the gcd of the numbers between [l,r] in the set u belongs to, if there is no number between [l,r],you can suppose the answer is -1. 1<=l<=r<=109
Because Zhanyl is a good person, so she guarantee 1<=u,v<=n above.
You need to tell Zhanyl the answer to each query.
Input
The first line of the input is a single integer T which is the number of test cases.Then comes the T test cases .
For each test case, the first line contains two integer n and m, n is the number of set initially, m is the number
of operations/querys.
Following line contains n integers, A 1, A 2, ... , A n, the value of i-th number.
Following m lines, each line is a operation or query.
Note that 1<=n,m<=10 5, 1<=A i<=10 9
For each test case, the first line contains two integer n and m, n is the number of set initially, m is the number
of operations/querys.
Following line contains n integers, A 1, A 2, ... , A n, the value of i-th number.
Following m lines, each line is a operation or query.
Note that 1<=n,m<=10 5, 1<=A i<=10 9
各种操作如上。
大裸数据结构啊,比赛的时候想敲的,不过很长时间没写这种多
颗树合并的题,而且有一个最关键的启发式合并的地方想歪了,认为复杂度不行,就没敲,现在想想还真是后悔,只怪自己的思维还不够严谨,要是在比赛中敲,不管能不能AC,都会比赛后敲来的激情啊。
好歹花了一天时间,第一次全部手写splay树的所有函数,debug的时候过于自信就没去看那几个函数,而且还过了自己出的很多数据,后来看到了,就一点点改,一直到所有的bug都找到了(我认为的),交上去还是TLE,比较庆幸的是这次写没有像写10天津那个题一样,RE了好长一排(那是第一次写指针splay),很多结构调试起来还是轻松的,但是由于种种细节过多,导致我一开始就看出来的错误有一个地方没有修改好,然后就一直T。。
一些花絮::
TLE持续中。。。。。
TLE持续中。。。。。
实在是好忧桑啊。。。。。
这日子没法过了。。。。。
怎么办怎么办。。。。。。。。
继续埋头看代码。。。。。
找到了!!!!
再来一发,还是TLE。。。。。
MD,爆粗口了。。。。。
好吧,先去赚点钱吧!!!!都是正事啊。。。
教别人游泳的时候一直无法专心,,,,,明明没错啊,,,
晚上回到寝室,杰哥帮忙跑了一发100000的数据,竟然跑不出来。。
这不科学
然后仔细一看,有个地方写傻了,,,,
233333333333333333333333333333
我乃绝世大sb,不能直视啊。。。
然后怒交一发,AC了!!!!!!
这个题思路很简单的,就按照题目告诉的模拟就好了,真正好的数据结构题不该是这种大裸的题吧,,,
还是贴个代码吧。。。不过代码略微有些含蓄+混乱。。。切勿随意模仿
/* **********************************************
Author : wuyiqi
Created Time: 2013-8-16 8:24:44
File Name : hdu 4680.cpp
*********************************************** */
#pragma comment(linker,"/STACK:100000000,100000000")
#include <cstring>
#include <cstdio>
#include <string>
#include <iostream>
using namespace std;
#define L x->c[0]
#define R x->c[1]
#define KT root->c[1]->c[0]
const int maxn = 300010;
const int lim = 1000000000;
inline int GCD(int a,int b) {
if(a<0||a>lim) return b;
if(b<0||b>lim) return a;
return !b ? a : GCD(b,a%b);
}
struct node {
struct node *c[2] , *fa;
int id;
int sz;
int gcd;
int val;
int who;
inline bool d() {
return fa->c[0] == this;
}
inline void setc(int d,node *s) {
c[d] = s;
s->fa = this;
}
inline void up() {
sz = c[0]->sz + c[1]->sz + 1;
gcd = GCD(c[0]->gcd,c[1]->gcd);
gcd = GCD(gcd,val);
}
inline void clear(node *null) {
c[0] = c[1] = null;
}
}NODE[maxn] , *null = &NODE[0];
node* Q[maxn];
node* ID[maxn];
int Type;
int n;
int top;
struct _x_x_{
int type;
node* root;
inline void Rotate(node *x,int f){
node *y = x->fa;
y->setc(!f,x->c[f]);
x->fa = y->fa;
if(y->fa != null) y->fa->setc(!y->d(),x);
x->setc(f,y);
y->up();
}
inline void Splay(node *x,node *goal) {
while(x->fa!=goal) {
if(x->fa->fa == goal) Rotate(x,x->d());
else {
int f = x->fa->d();
x->d() == f ? Rotate(x->fa,f) : Rotate(x,!f);
Rotate(x,f);
}
}
x->up();
if(goal == null) {
root = x;
}
}
inline void RTO(int k,node *goal) {
node *x = root;
while(L->sz + 1 != k) {
if(k < L->sz + 1) x = L;
else {
k -= L->sz + 1;
x = R;
}
}
Splay(x,goal);
}
inline node* new_node(node *fa,int v) {
node *x = &NODE[++top];
x->id = top;
x->c[0] = x->c[1] = null;
x->sz = 1;
x->val = v;
x->gcd = v;
x->fa = fa;
ID[top] = x;
return x;
}
inline void init(int v) {
root = new_node(null,v);
type = ++Type;
root->who = type;
}
inline void Del_root() {
node *t = root;
if(t->c[1] != null) {
root = t->c[1];
RTO(1,null);
root->c[0] = t->c[0];
if(root->c[0] != null)
root->c[0]->fa = root;
} else {
root = root->c[0];
}
root->fa = null;
if(root != null) root->up();
}
inline void Delete(node *x) {
Splay(x,null);
Del_root();
}
inline void Insert(node *x) {
x->clear(null);
//插入一个节点前不能忘记清空它的左右儿子
insert(root,x);
Splay(x,null);
x->who = type;
}
inline void insert(node* &x,node *y) {
if(x == null) {
x = y;
return ;
}
if(y->val <= x->val) {
insert(x->c[0],y);
x->c[0]->fa = x;
} else {
insert(x->c[1],y);
x->c[1]->fa = x;
}
x->up();
}
inline void Insert(int v) {
node *x = new_node(null,v);
insert(root,x);
Splay(x,null);
x->who = type;
}
inline void Change(int u,int v) {
node *tmp = ID[u+2*n];
Splay(tmp,null);
Del_root();
tmp->val = v;
Insert(tmp);
}
node *find_succ(node *x,int v) {
if(x == null) return x;
if(x->val == v) return x;
else if(x->val > v) {
node *tmp = find_succ(x->c[0],v);
return tmp == null ? x : tmp;
}else {
return find_succ(x->c[1],v);
}
}
inline int find_succ(int v){
node* tmp = find_succ(root,v);
Splay(tmp,null) ;
return tmp->val;
}
inline int Gao() {
if(root->sz <= 4) return root->sz - 2;
RTO(2,null);
int a = root->val;
RTO(3,null);
int b = root->val;
int ans = 2;
while(true){
if(a + b > lim) break;
int c = find_succ(a+b);
if(c > lim || c == -1) break;
a = b; b = c;
ans++;
}
return ans;
}
void vist(node *x) {
if(x != null) {
printf("节点 %2d: 左儿子: %2d 右儿子: %2d sz:%2d val=%2d gcd: %2d\n",x->id,x->c[0]->id,x->c[1]->id,x->sz,x->val,x->gcd);
vist(x->c[0]);
vist(x->c[1]);
}
}
void debug() {
puts("******************************************");
vist(root);
puts("*****************************************");
}
node *Find_pre(node *x,int v) {
if(x == null) return x;
if(x->val < v) {
node *tmp = Find_pre(x->c[1],v);
return tmp == null ? x : tmp;
} else {
return Find_pre(x->c[0],v);
}
}
node *Find_pre(int v) {
node* tmp = Find_pre(root,v);
Splay(tmp,null);
return tmp;
}
node *Find_succ(node *x,int v) {
if(x == null) return x;
if(x->val > v) {
node *tmp = Find_succ(x->c[0],v);
return tmp == null ? x : tmp;
} else {
return Find_succ(x->c[1],v);
}
}
node *Find_succ(int v) {
node* tmp = Find_succ(root,v);
Splay(tmp,null);
return tmp;
}
void Assert(string s) {
cout<<s<<endl;
}
int Solve(int l,int r) {
node *pre = Find_pre(l);
node *succ = Find_succ(r);
if(pre == null || succ == null) Assert("越界了");
// printf("preid=%d succid=%d\n",pre->id,succ->id);
// pre : the first element strictly less than l
// succ: the first element strictly bigger than r
Splay(pre,null);
Splay(succ,root);
return KT->gcd;
}
void Merge(_x_x_ &tree) {
int head = 0, tail = 0;
tree.RTO(1,null);
tree.RTO(tree.root->sz,tree.root);
Q[++tail] = tree.KT;
while(head < tail) {
node *fr = Q[++head];
if(fr->c[0] != null) Q[++tail] = fr->c[0];
if(fr->c[1] != null) Q[++tail] = fr->c[1];
Insert(fr);//此处吐血了一整天,上面的改回来了,这里却没改insert(root,fr);
fr->who = type;
}
tree.KT = null;
tree.root->c[1]->up();
tree.root->up();
}
}spt[maxn];
void prepare() {
null->id = 0;
null->c[0] = null->c[1] = null->fa = NULL;
null->sz = null->val = 0;
null->gcd = -1;
Type = 0;
top = 0;
}
int main()
{
// freopen("input.txt","r",stdin);
// freopen("cmp.txt","w",stdout);
int t,m,ca=1,op,u,v,l,r,x;
scanf("%d",&t);
while(t--) {
prepare();
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++){
spt[i].init(-1);
spt[i].Insert(lim+1);
}
for(int i = 1,a; i <= n; i++) {
scanf("%d",&a);
spt[i].Insert(a);
}
int tot = 0;
printf("Case #%d:\n",ca++);
while(m--) {
scanf("%d",&op);
if(op == 1) {
scanf("%d%d",&u,&v);
node *tmp1 = ID[u+2*n] , *tmp2 = ID[v+2*n];
int tree1 = tmp1->who;
int tree2 = tmp2->who;
if(tree1 == tree2) continue;
int sz1 = spt[tree1].root->sz;
int sz2 = spt[tree2].root->sz;
if(sz1 > sz2) {
spt[tree1].Merge(spt[tree2]);
} else {
spt[tree2].Merge(spt[tree1]);
}
// if(spt[tree1].root->sz < 2 || spt[tree2].root->sz < 2){
// return 0;
// break;
// }
// spt[tree1].debug();
} else if(op == 2) {
scanf("%d%d",&u,&v);
node *tmp1 = ID[u+2*n] , *tmp2 = ID[v+2*n];
int tree1 = tmp1->who;
int tree2 = tmp2->who;
// spt[tree1].debug(); spt[tree2].debug();
spt[tree1].Delete(tmp1);
// if(spt[tree2].root->sz < 2) return 0;
spt[tree2].Insert(tmp1);
// spt[tree1].debug(); spt[tree2].debug();
} else if(op == 3) {
scanf("%d%d",&u,&x);
node *tmp = ID[u+2*n];
int tree = tmp->who;
spt[tree].Change(u,x);
} else if(op == 4) {
scanf("%d",&u);
node *tmp = ID[u+2*n];
int tree = tmp->who;
printf("%d\n",spt[tree].Gao());
} else {
scanf("%d%d%d",&u,&l,&r);
node *tmp = ID[u+2*n];
int tree = tmp->who;
// printf("id=%d tree=%d\n",tmp->id,tree);
printf("%d\n",spt[tree].Solve(l,r));
}
}
}
return 0;
}
浙公网安备 33010602011771号