bzoj3123: [Sdoi2013]森林

news/2024/12/13 16:17:13/

题面在这里

题意:

给一个森林,森林有n个节点m条边。
现在有两种操作:
1.Q x y k 表示询问x-y这条链上点权的第k小。保证x,y在同一个连通块里。
2.L x y 表示链接x,y两点。保证x,y在不同的连通块里。
要求强制在线,last表示上一次的答案,每次x,y,k都要异或last.初始为0.

做法:

权值第k小想到主席树。(发现和上一题基本一样除了连接两个点的操作)
连接两个点其实就是把两棵树合并。
然后我们启发式合并,暴力地把小的树接到大的树上。
然后大概就没了。
另外这题一个坑的地方就是那个testcase是当前数据的测试点编号,不是数据组数!

代码:

/*************************************************************Problem: bzoj 3123 [Sdoi2013]森林User: fengyuanLanguage: C++Result: AcceptedTime: 12524 msMemory: 131972 kbSubmit_Time: 2018-01-08 14:33:42
*************************************************************/#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<cctype>
#define mid (l+r>>1)
using namespace std;
typedef long long LL;inline LL read()
{char ch = getchar(); LL x = 0; int op = 1;for(; !isdigit(ch); ch = getchar()) if(ch == '-') op = -1;for(; isdigit(ch); ch = getchar()) x = x*10 + ch-'0';return x*op;
}
inline void write(LL a) { if(a < 0) putchar('-'); if(a >= 10) write(a/10); putchar(a%10+'0'); }const int N = 100010, M = 10000010;
int n, m, q, cnt, tot, all;
int head[N], p[N], rt[N], L[M], R[M], sum[M], depth[N], f[N][19], fa[N], sz[N], num[N], a[N];
char opt[5];
struct Edge{int to, nxt;Edge() {}Edge(int x, int y) { to = x, nxt = y; }
}e[N<<1];inline int getFa(int v) { return v == fa[v] ? v : fa[v] = getFa(fa[v]); }
inline void addEdge(int x, int y) { e[++ cnt] = Edge(y, head[x]); head[x] = cnt; }
inline void insert(int pre, int &rt, int l, int r, int x)
{rt = ++ all; sum[rt] = sum[pre]+1; L[rt] = L[pre]; R[rt] = R[pre];if(l == r) return;if(x <= mid) insert(L[pre], L[rt], l, mid, x);else insert(R[pre], R[rt], mid+1, r, x);
}
inline int query(int x, int y, int lca, int fa_lca, int l, int r, int k)
{if(l == r) return num[l];int lsum = sum[L[x]]+sum[L[y]]-sum[L[lca]]-sum[L[fa_lca]];if(lsum >= k) return query(L[x], L[y], L[lca], L[fa_lca], l, mid, k);else return query(R[x], R[y], R[lca], R[fa_lca], mid+1, r, k-lsum);
}
inline void dfs(int u, int lst, int s)
{depth[u] = s; f[u][0] = lst;for(int i = 1; i <= 17; i ++) f[u][i] = f[f[u][i-1]][i-1];insert(rt[lst], rt[u], 1, tot, a[u]);for(int i = head[u]; i; i = e[i].nxt) {int v = e[i].to; if(v == lst) continue;dfs(v, u, s+1);}
}
inline int LCA(int x, int y)
{if(depth[x] < depth[y]) swap(x, y);int tmp = depth[x] - depth[y];for(int i = 17; i >= 0; i --)if(tmp>>i&1) x = f[x][i];if(x == y) return x;for(int i = 17; i >= 0; i --)if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];return f[x][0];
}
int main()
{int Test = read();n = read(), m = read(), q = read(); cnt = 0; memset(head, 0, sizeof head);for(int i = 1; i <= n; i ++) a[i] = read(), num[i] = a[i];sort(num+1, num+1+n); tot = unique(num+1, num+1+n)-num-1;//p[i]是第i个数离散化后的编号for(int i = 1; i <= n; i ++) a[i] = lower_bound(num+1, num+1+tot, a[i])-num;for(int i = 1; i <= n; i ++) fa[i] = i, sz[i] = 1;for(int i = 1; i <= m; i ++) {int x = read(), y = read(), fx, fy;addEdge(x, y); addEdge(y, x);fx = getFa(x); fy = getFa(y);if(fx != fy) fa[fx] = fy, sz[fy] += sz[fx];}memset(depth, 0, sizeof depth); all = 0;memset(sum, 0, sizeof sum); memset(rt, 0, sizeof rt); memset(L, 0, sizeof L); memset(R, 0, sizeof R);memset(f, 0, sizeof f);for(int i = 1; i <= n; i ++) if(!depth[i]) { int rt = getFa(i); dfs(rt, 0, 1); }int lastans = 0;while(q --) {scanf("%s", opt);int x = read()^lastans, y = read()^lastans, k, z;z = LCA(x, y);if(opt[0] == 'Q') {k = read()^lastans; lastans = query(rt[x], rt[y], rt[z], rt[f[z][0]], 1, tot, k);write(lastans), puts("");} else {addEdge(x, y); addEdge(y, x);int fx = getFa(x), fy = getFa(y);if(sz[fx] > sz[fy]) swap(fx, fy), swap(x, y);fa[fx] = fy; sz[fy] += sz[fx];f[x][0] = y; dfs(x, y, depth[y]+1);//启发式合并}}return 0;
}

http://www.ppmy.cn/news/846254.html

相关文章

bzoj3123

3123: [Sdoi2013]森林 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 1846 Solved: 574[Submit][Status][Discuss] Description Input 第一行包含一个正整数testcase&#xff0c;表示当前测试数据的测试点编号。保证1≤testcase≤20。 第二行包含三个整数N&#xff0c;M…

POJ 3123

https://cn.vjudge.net/problem/POJ-3123 题意&#xff1a; n 个城市&#xff0c;m 条路&#xff0c;给定八个点&#xff08;也就是四对&#xff09;&#xff0c;使每队点连通且总权和最小。 分析&#xff1a; dp[i][j] 表示 i 状态下以 j 为起点的最小总权和。 #include …

Flutter:第三方常用库整理

前言 随着Flutter的不断学习&#xff0c;接触了不少第三方的库。因此打算进行简单的整理。 dio 简介 一个强大的Dart/FlutterHTTP客户端&#xff0c;支持全局配置&#xff0c; 拦截器、表单数据、请求取消、文件上传/下载、 超时和自定义适配器等。 官方地址 https://pub-w…

Redis_客户端命令和数据操作(3)

目录 切换数据库 键命令 数据结构 string类型 hash类型 list类型 set类型 zset类型 查看中文value 源码等资料获取方法 切换数据库 redis数据库没有名称&#xff0c;默认有16个&#xff0c;通过0-15来标识&#xff0c;连接redis默认选择第一个数据库&#xff0c;可以…

青龙傻妞onebot不能用,改用cqhttp+傻妞/qqbot

不知为何我的onebot突然用不了了&#xff0c;傻妞还正常&#xff0c;这就需要改用cqhttp了 下面介绍cqhttp登录不上的问题 一般来说cqhttp还是很好安装的随便一搜就很多&#xff0c;这里先讲一下QQ扫码登录不成功问题 原因是&#xff0c;tx检测qq登录有风险&#xff0c;网络…

ONEBOT开发板

ONEBOT开发板 制作传感器的新方式—搭积木式制作传感器 介绍 ONEBOT是小米生态链爱其科技推出的开源传感器创作平台&#xff0c;提供了机器人、物联网应用创作原型&#xff0c;让每个人都享受创造科技的乐趣。 为电子爱好者、DIY、创客、教育等提供了制作传感器的 新方式&a…

『Nonebot 插件编写教程』nonebot2处理消息的完整过程

文章目录 前言捕获消息处理消息Bot机器人参数Event事件参数 回复消息字符串与Message调用MessageSegment接口 前言 前面已经有不止一篇博客教大家如何搭建nonebot2环境了大家可以去专栏查看&#xff0c;这篇博客并不会再次带大家来搭建nonebot2环境&#xff0c;而是着手与插件的…

Ubuntu搭建zhenxunbot聊天机器人

GitHub - HibiKier/zhenxun_bot: 基于 Nonebot2 和 go-cqhttp 开发&#xff0c;以 postgresql 作为数据库&#xff0c;非常可爱的绪山真寻bot 1.安装python3.9 apt和手动编译源码选一个&#xff0c;记得装pip pip改清华源&#xff0c;apt改国内随便哪个源 2.apt安装下面这一…