[BZOJ 3123]森林
这题和 COT1 一定有 JQ 喵~
线段树的启发式合并,每次要连接两个点时就对比较小的那棵树暴力 DFS 一边
然后均摊时间依旧是 logn 的,均摊真是世界上最邪恶的东西了……
然后这题的数据是要卖萌么?!
testcase 的存在意义是被阿卡林噎掉了么?!
- #include <cstdio>
- #include <cstring>
- #include <algorithm>
- const int sizeOfPoint=;
- const int sizeOfEdge=;
- const int sizeOfNode=;
- inline int lg(int);
- inline void swap(int & , int & );
- inline char getch();
- inline int getint();
- inline void putint(int);
- struct edge {int point; edge * next;};
- edge memory_edge[sizeOfEdge], * port_edge=memory_edge;
- inline edge * newedge(int, edge * );
- inline void link(int, int);
- struct node {int c; node * l , * r; inline node();};
- node * null=new node();
- node memory_node[sizeOfNode], * port_node=memory_node;
- inline node * newnode(node * =null);
- node * insert(node * , int, int, int);
- int b[sizeOfPoint], s[sizeOfPoint];
- int find(int);
- inline void merge(int, int);
- int testcase;
- int N, M, T, U;
- int p[sizeOfPoint], q[sizeOfPoint];
- int f[sizeOfPoint], d[sizeOfPoint], a[][sizeOfPoint];
- edge * e[sizeOfPoint];
- node * t[sizeOfPoint];
- inline void clear();
- inline bool cmp(int, int);
- inline void discretization();
- void dfs(int);
- inline int lca(int, int);
- inline int query(int, int, int);
- int main()
- {
- int lastans=;
- testcase=getint();
- for (testcase=;testcase;testcase--)
- {
- N=getint(), M=getint(), T=getint();
- clear();
- for (int i=;i<=N;i++)
- p[i]=getint();
- for (int i=;i<=M;i++)
- {
- int u=getint(), v=getint();
- link(u, v);
- }
- discretization();
- for (int i=;i<=N;i++) if (f[i]==-)
- {
- f[i]=; d[i]=;
- dfs(i);
- }
- for (int i=;i<=T;i++)
- {
- char c=getch(); int x=getint()^lastans, y=getint()^lastans;
- if (c=='Q')
- {
- int k=getint()^lastans;
- lastans=query(x, y, k);
- putint(lastans);
- }
- else
- {
- int bx=find(x), by=find(y);
- if (bx==by) continue;
- if (s[bx]<s[by]) swap(x, y);
- link(x, y);
- f[y]=x; d[y]=d[x]+;
- dfs(y);
- }
- }
- }
- return ;
- }
- inline int lg(int x)
- {
- return -__builtin_clz(x);
- }
- inline void swap(int & x, int & y)
- {
- int z=x;
- x=y;
- y=z;
- }
- inline char getch()
- {
- register char ch;
- do ch=getchar(); while (ch!='L' && ch!='Q');
- return ch;
- }
- inline int getint()
- {
- register int num=;
- register char ch=, last;
- do last=ch, ch=getchar(); while (ch<'' || ch>'');
- do num=num*+ch-'', ch=getchar(); while (ch>='' && ch<='');
- if (last=='-') num=-num;
- return num;
- }
- inline void putint(int num)
- {
- char stack[];
- register int top=;
- if (num==) stack[top=]='';
- if (num<) putchar('-'), num=-num;
- for ( ;num;num/=) stack[++top]=num%+'';
- for ( ;top;top--) putchar(stack[top]);
- putchar('\n');
- }
- inline edge * newedge(int point, edge * next)
- {
- edge * ret=port_edge++;
- ret->point=point; ret->next=next;
- return ret;
- }
- inline void link(int u, int v)
- {
- e[u]=newedge(v, e[u]);
- e[v]=newedge(u, e[v]);
- merge(u, v);
- }
- inline node::node()
- {
- this->c=;
- this->l=this;
- this->r=this;
- }
- inline node * newnode(node * t)
- {
- node * newt=port_node++;
- *newt=*t;
- return newt;
- }
- node * insert(node * t, int l, int r, int k)
- {
- t=newnode(t);
- t->c++;
- if (l==r) return t;
- int m=(l+r)>>;
- if (k<=m) t->l=insert(t->l, l, m, k);
- else t->r=insert(t->r, m+, r, k);
- return t;
- }
- int find(int u)
- {
- return !b[u]?u:b[u]=find(b[u]);
- }
- inline void merge(int u, int v)
- {
- u=find(u); v=find(v);
- b[v]=u; s[u]+=s[v];
- }
- inline void clear()
- {
- port_edge=memory_edge;
- memset(e, , sizeof(e));
- port_node=memory_node;
- for (int i=;i<=N;i++) t[i]=null;
- memset(f, -, sizeof(f));
- memset(d, -, sizeof(d));
- memset(b, , sizeof(b));
- memset(a, , sizeof(a));
- for (int i=;i<=N;i++) s[i]=;
- }
- inline bool cmp(int a, int b)
- {
- return p[a]<p[b];
- }
- inline void discretization()
- {
- static int k[sizeOfPoint];
- for (int i=;i<=N;i++) k[i]=i;
- std::sort(k+, k+N+, cmp);
- q[U=]=p[k[]]; p[k[]]=;
- for (int i=;i<=N;i++)
- {
- if (p[k[i]]>q[U]) q[++U]=p[k[i]];
- p[k[i]]=U;
- }
- }
- void dfs(int u)
- {
- t[u]=insert(t[f[u]], , U, p[u]);
- if (d[u]>)
- {
- int lim=lg(d[u]);
- a[][u]=f[u];
- for (int i=;i<=lim;i++)
- a[i][u]=a[i-][a[i-][u]];
- for (int i=lim+;i<;i++)
- a[i][u]=;
- }
- for (edge * i=e[u];i;i=i->next) if (i->point!=f[u])
- {
- f[i->point]=u;
- d[i->point]=d[u]+;
- dfs(i->point);
- }
- }
- inline int lca(int u, int v)
- {
- if (d[u]<d[v]) swap(u, v);
- while (int dist=d[u]-d[v]) u=a[__builtin_ctz(dist)][u];
- if (u==v) return u;
- for (int i=;i>=;i--)
- if (a[i][u]!=a[i][v])
- u=a[i][u],
- v=a[i][v];
- return f[u];
- }
- inline int query(int a, int b, int k)
- {
- int c=lca(a, b), d=f[c];
- node * ta=t[a], * tb=t[b], * tc=t[c], * td=t[d];
- int l=, r=U, m;
- for ( ;l<r; )
- {
- m=(l+r)>>;
- if (ta->l->c+tb->l->c-tc->l->c-td->l->c>=k)
- {
- ta=ta->l; tb=tb->l; tc=tc->l; td=td->l;
- r=m;
- }
- else
- {
- k-=ta->l->c+tb->l->c-tc->l->c-td->l->c;
- ta=ta->r; tb=tb->r; tc=tc->r; td=td->r;
- l=m+;
- }
- }
- return q[l];
- }
又 R 又 T 一时爽
[BZOJ 3123]森林的更多相关文章
- BZOJ 3123 森林(函数式线段树)
题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3123 题意: 思路:总的来说,查询区间第K小利用函数式线段树的减法操作.对于两棵树的合并 ...
- BZOJ - 3123 森林 (可持久化线段树+启发式合并)
题目链接 先把初始边建成一个森林,每棵树选一个根节点递归建可持久化线段树.当添加新边的时候,把结点数少的树暴力重构,以和它连边的那个点作为父节点继承线段树,并求出倍增数组.树的结点数可以用并查集来维护 ...
- [BZOJ 3123] [SDOI 2013]森林(可持久化线段树+并查集+启发式合并)
[BZOJ 3123] [SDOI 2013]森林(可持久化线段树+启发式合并) 题面 给出一个n个节点m条边的森林,每个节点都有一个权值.有两种操作: Q x y k查询点x到点y路径上所有的权值中 ...
- 【sdoi2013】森林 BZOJ 3123
Input 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负整数 ...
- BZOJ 3123: [Sdoi2013]森林 [主席树启发式合并]
3123: [Sdoi2013]森林 题意:一个森林,加边,询问路径上k小值.保证任意时刻是森林 LCT没法搞,树上kth肯定要用树上主席树 加边?启发式合并就好了,小的树dfs重建一下 注意 测试点 ...
- bzoj 3123: [Sdoi2013]森林(45分暴力)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4184 Solved: 1235[Submit][Status ...
- AC日记——[Sdoi2013]森林 bzoj 3123
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3216 Solved: 944[Submit][Status] ...
- Bzoj 3123: [Sdoi2013]森林(主席树+启发式合并)
3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MB Description Input 第一行包含一个正整数testcase,表示当前 ...
- ●BZOJ 3123 [Sdoi2013]森林
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3123 题解: 主席树,在线,启发式合并 简单版(只有询问操作):[2588: Spoj 10 ...
随机推荐
- Oracle查询数据库中的所有表
SELECT A.TABLE_NAME 表英文名, A.TAB_COMMENTS 表中文名, A.COLUMN_ID 序号, A.COLUMN_NAME 英文名, ...
- intellij idea 初步环境熟悉
刚进来天渔项目组,连开发环境都是新的,学习至上 so 从eclipse过度过来还是有段时间的,期间虽然懵懂,但是也要坚持不耻下问 好了一下是idea的官网http://confluence.jetbr ...
- ThinkPHP(3)SQL查询语句
ThinkPHP中对查询语句,包含了基本的查询方式.表达方式.快速查询.区间查询.组合查询.SQL查询.动态查询和子查询. 一.查询方式 ThinkPHP提供了三种基本的查询方式:字符串条件查询.索引 ...
- html页面3秒后自动跳转的方法有哪些
在进行web前端开发实战练习时,我们常常遇到一种问题就是,web前端开发应该如何实现页面N秒之后自动跳转呢?通过查找相关html教程,总结了3个方法: 方法1: 最简单的一种:直接在前面<hea ...
- 使用USRP探索无线世界 Part 1:USRP从入门到追踪飞机飞行轨迹
温馨提示:请自觉遵守无线电管理法规,依法设置和使用无线电设备 0×00 前言 USRP是数款流行的SDR硬件中功能和应用都相对成熟的一款产品,从WIFI协议.ZigBee协议.RFID协议.GSM通信 ...
- 【转】Duff's Device
在看strcpy.memcpy等的实现发现用了内存对齐,每一个word拷贝一次的办法大大提高了实现效率,参加该blog(http://totoxian.iteye.com/blog/1220273). ...
- sudo apt-get install apache2 php7.0 php7.0-mysql mysql-server
sudo apt-get install apache2 php7.0 php7.0-mysql mysql-server sudo apt-get install libapache2-mod-ph ...
- UE4 WCF RestFul 服务器 读取JSON 数据并解析 简单实例
Note:不知道为什么通过Txt读取的JsonString,如果TXT 不是ANSI编码的话,会报JsonArrayStringToUStruct Unable to parse. bool UWg ...
- 胡说REST(REpresentational State Transfer)
Roy T. Fielding的2000年在他的博士论文中提出REpresentational State Transfer这一软件架构风格,相比"表述性状态转移"等等类似的拗口的 ...
- 如何让iOS 保持界面流畅?这些技巧你知道吗
如何让iOS 保持界面流畅?这些技巧你知道吗 作者:ibireme这篇文章会非常详细的分析 iOS 界面构建中的各种性能问题以及对应的解决思路,同时给出一个开源的微博列表实现,通过实际的代码展示如 ...