题解 e
第一眼看貌似可以树剖,然而那个绝对值不知怎么维护
求最小连通块我只会\(k^2\)
主席树貌似可以用来查询区间内与某个数差的绝对值的最小值?
确实,每次查大于等于该数的最小数和小于等于该数的最大数即可
至于具体实现,实际上可以转化为求一个区间内最左/右边的数
很容易写出一个线段树上\(O(nlogn)\)的暴力遍历
但这里用的只要求第一个,可以按顺序找,找到第一个就跳出,单次复杂度\(O(logn)\)
至于查询区间和log划分区间间的问题,到了一个节点,如果它已经不在查询区间中,返回一个标记值即可
至于求连通块的问题:
- 一棵树上,给定n个点,求这n个点所在的最小连通块中的最值之类的东西
其实找到它们的lca,\(O(k)\)遍历一次,每次查询一个点与lca之间的路径即可
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, q, typ;
int head[N], size, a[N], x[N];
struct edge{int to, next;}e[N<<1];
inline void add(int s, int t) {edge* k=&e[++size]; k->to=t; k->next=head[s]; head[s]=size;}
//struct que{int r, k; vector<int> v;}que[N];
namespace force{
bool vis[N];
int dfs(int u, int to, int r, int fa) {
if (u==to) return abs(a[u]-r);
for (int i=head[u],v,t; i; i=e[i].next) {
v = e[i].to;
if (v!=fa) {
t=dfs(v, to, r, u);
if (t!=-1) return min(t, abs(a[u]-r));
}
}
return -1;
}
void solve() {
for (int i=1,r,k,ans; i<=q; ++i) {
ans=INF;
r=read(); k=read();
//cout<<r<<' '<<k<<endl;
for (int j=1; j<=k; ++j) x[j]=read();
for (int j=1; j<=k; ++j)
for (int h=j; h<=k; ++h)
ans=min(ans, dfs(x[j], x[h], r, 0));
printf("%d\n", ans);
}
exit(0);
}
}
namespace force2{
bool vis[N];
int rot;
int dfs(int u, int r, int fa) {
int ans=INF;
if (vis[u]) ans=min(ans, abs(a[u]-r));
for (int i=head[u],v,t; i; i=e[i].next) {
v = e[i].to;
if (v!=fa) {
t=dfs(v, r, u);
if (t!=-1) ans=min(ans, min(t, abs(a[u]-r)));
if (!ans) return 0;
}
}
return ans==INF?-1:ans;
}
void solve() {
for (int i=1,r,k,ans; i<=q; ++i) {
ans=INF;
r=read(); k=read();
//cout<<r<<' '<<k<<endl;
for (int j=1; j<=k; ++j) x[j]=read(), vis[x[j]]=1;
printf("%d\n", dfs(x[1], r, 0));
for (int j=1; j<=k; ++j) vis[x[j]]=0;
}
exit(0);
}
}
namespace task{
int dep[N], siz[N], msiz[N], mson[N], top[N], id[N], rk[N], fa[N], tot;
int rot[N], tot2, r[N*3], k[N*3], uni[N<<3], usize, lst;
vector<ll> x[N*3];
struct pst{
int tl, tr, cnt, lson, rson;
#define t(p) tree[p]
#define tl(p) tree[p].tl
#define tr(p) tree[p].tr
#define cnt(p) tree[p].cnt
#define l(p) tree[p].lson
#define r(p) tree[p].rson
#define pushup(p) cnt(p)=cnt(l(p))+cnt(r(p))
}tree[N*80];
int upd(int p1, int p2, int l, int r, int pos) {
p1=++tot2; t(p1)=t(p2); tl(p1)=l; tr(p1)=r;
if (l>=r) {cnt(p1)=cnt(p2)+1; return p1;}
int mid=(l+r)>>1;
if (pos<=mid) l(p1)=upd(l(p1), l(p2), l, mid, pos);
else r(p1)=upd(r(p1), r(p2), mid+1, r, pos);
pushup(p1);
return p1;
}
int qleft(int p1, int p2, int l, int r) {
//cout<<"qleft "<<p1<<' '<<p2<<' '<<l<<' '<<r<<endl;
if (l>tr(p2) || r<tl(p2)) return 0;
if (tl(p2)==tr(p2)) {/*cout<<"return "<<cnt(p2)-cnt(p1)<<' '<<tl(p2)<<endl;*/ return (cnt(p2)-cnt(p1))?tl(p2):0;}
int mid=(tl(p2)+tr(p2))>>1, ans=INF, t;
if (l<=mid && cnt(l(p2))-cnt(l(p1))) {t=qleft(l(p1), l(p2), l, r); ans=min(ans, !t?INF:t);}
if (ans!=INF) return ans;
if (r>mid && cnt(r(p2))-cnt(r(p1))) {t=qleft(r(p1), r(p2), l, r); ans=min(ans, !t?INF:t);}
//puts("error");
return ans==INF?0:ans;
}
int qright(int p1, int p2, int l, int r) {
//cout<<"qright: "<<p1<<' '<<p2<<' '<<l<<' '<<r<<endl;
if (l>tr(p2) || r<tl(p2)) return 0;
if (tl(p2)==tr(p2)) {/*cout<<"return "<<cnt(p2)-cnt(p1)<<' '<<tl(p2)<<endl;*/ return (cnt(p2)-cnt(p1))?tl(p2):0;}
int mid=(tl(p2)+tr(p2))>>1, ans=0, t;
if (r>mid && cnt(r(p2))-cnt(r(p1))) {t=qright(r(p1), r(p2), l, r); ans=max(ans, t);}
if (ans) return ans;
if (l<=mid && cnt(l(p2))-cnt(l(p1))) {t=qright(l(p1), l(p2), l, r); ans=max(ans, t);}
//puts("error");
return ans;
}
void dfs1(int u, int pa) {
siz[u]=1;
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (v==pa) continue;
dep[v]=dep[u]+1; fa[v]=u;
dfs1(v, u);
siz[u]+=siz[v];
if (siz[v]>msiz[u]) msiz[u]=siz[v], mson[u]=v;
}
}
void dfs2(int u, int f, int t) {
top[u]=t;
id[u]=++tot;
rot[tot]=upd(rot[tot], rot[tot-1], 1, usize, lower_bound(uni+1, uni+usize+1, a[u])-uni);
//cout<<"upd: "<<tot<<' '<<u<<' '<<lower_bound(uni+1, uni+usize+1, a[u])-uni<<' '<<uni[lower_bound(uni+1, uni+usize+1, a[u])-uni]<<endl;
rk[tot]=u;
if (!mson[u]) return ;
dfs2(mson[u], u, t);
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
if (v!=f && v!=mson[u]) dfs2(v, u, v);
}
}
int query(int a, int b, int r) {
//cout<<"query "<<a<<' '<<b<<' '<<r<<endl;
int ans=INF, q1, q2;
int rb=lower_bound(uni+1, uni+usize+1, r)-uni;
//cout<<"rb: "<<rb<<endl;
while (top[a]!=top[b]) {
if (dep[top[a]]<dep[top[b]]) swap(a, b);
//cout<<"qid: "<<id[top[a]]<<' '<<id[a]<<endl;
q1=qleft(rot[id[top[a]]-1], rot[id[a]], rb, usize), q2=qright(rot[id[top[a]]-1], rot[id[a]], 1, rb);
//cout<<"q1q2: "<<q1<<' '<<q2<<endl;
ans=min(ans, min(q1?(uni[q1]-r):INF, q2?(r-uni[q2]):INF));
if (!ans) return 0;
a = fa[top[a]];
}
if (dep[a]>dep[b]) swap(a, b);
//cout<<"qid: "<<id[a]<<' '<<id[b]<<endl;
q1=qleft(rot[id[a]-1], rot[id[b]], rb, usize), q2=qright(rot[id[a]-1], rot[id[b]], 1, rb);
//cout<<"q1q2: "<<q1<<' '<<q2<<endl;
ans=min(ans, min(q1?(uni[q1]-r):INF, q2?(r-uni[q2]):INF));
return ans;
}
int lca(int a, int b) {
while (top[a]!=top[b]) {
if (dep[top[a]]<dep[top[b]]) swap(a, b);
a = fa[top[a]];
}
if (dep[a]>dep[b]) swap(a, b);
return a;
}
void init() {
dep[1]=1;
dfs1(1, 0);
dfs2(1, 0, 1);
}
void solve() {
for (int i=1; i<=q; ++i) {
r[i]=read(); k[i]=read(); uni[++usize]=r[i];
for (int j=1,t; j<=k[i]; ++j) {t=read(); x[i].push_back(t);}
}
for (int i=1; i<=n; ++i) uni[++usize]=a[i];
//cout<<"usize: "<<usize<<endl;
//cout<<"uni: "; for (int i=1; i<=usize; ++i) cout<<uni[i]<<' '; cout<<endl;
sort(uni+1, uni+usize+1);
usize=unique(uni+1, uni+usize+1)-uni-1;
//cout<<"usize: "<<usize<<endl;
//cout<<"uni: "; for (int i=1; i<=usize; ++i) cout<<uni[i]<<' '; cout<<endl;
init();
for (int i=1,anc,ans; i<=q; ++i) {
anc=(x[i][0]-1+lst*typ)%n+1, ans=INF;
for (int j=1; j<k[i]&&anc!=1; ++j) anc=lca(anc, (x[i][j]-1+lst*typ)%n+1);
//cout<<"anc: "<<anc<<endl;
for (int j=0; j<k[i]&&ans; ++j) ans=min(ans, query((x[i][j]-1+lst*typ)%n+1, anc, r[i])); //, cout<<"nowans: "<<ans<<endl;
printf("%d\n", ans);
lst=ans;
}
//cout<<qleft(rot[0], rot[3], 1, 5)<<endl;
//cout<<qright(rot[1], rot[3], 1, 3)<<endl;
}
}
signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif
bool same=1, less1=1, ris1=1, chain=1;
n=read(); q=read(); typ=read();
if (!q) return 0;
for (int i=1; i<=n; ++i) {
a[i]=read();
if (i!=1 && a[i]!=a[i-1]) same=0;
}
for (int i=1,u,v; i<n; ++i) {
u=read(); v=read();
add(u, v); add(v, u);
if (v!=u+1) chain=0;
}
task::solve();
#if 0
if (n<=1000) force2::solve();
for (int i=1,r,k; i<=q; ++i) {
r=read(); k=read();
for (int j=1; j<=k; ++j) x[j]=read(), force2::vis[x[j]]=1;
if (!k) continue;
else if (k==1 || same) printf("%d\n", abs(a[x[1]]-r));
else printf("%d\n", force2::dfs(x[1], r, 0));
for (int j=1; j<=k; ++j) force2::vis[x[j]]=0;
//else if (r==1) printf("%d\n", task2::qmin(1,
}
#endif
return 0;
}
题解 e的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
- JSOI2016R3 瞎BB题解
题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...
随机推荐
- CSS 奇思妙想 | 巧妙的实现带圆角的三角形
之前在这篇文章中 -- <老生常谈之 CSS 实现三角形>,介绍了 6 种使用 CSS 实现三角形的方式. 但是其中漏掉了一个非常重要的场景,如何使用纯 CSS 实现带圆角的三角形呢?,像 ...
- Java | 方法的定义 & 重载 & 递归
方法 方法就是一段用来完成特定功能的代码片段. 方法用于定义该类或该类的实例的行为特征和功能实现.方法是类和对象行为特征的抽象.在面向对象中,整个程序的基本单位是类,方法是从属于类和对象的. 方法 ...
- CF277E Binary Tree on Plane
CF277E Binary Tree on Plane 题目大意 给定平面上的 \(n\) 个点,定义两个点之间的距离为两点欧几里得距离,求最小二叉生成树. 题解 妙啊. 难点在于二叉的限制. 注意到 ...
- VS Code 下载安装并设置中文面板显示
下载: 下载地址:https://code.visualstudio.com/ 微软在2015年4月30日Build 开发者大会上正式宣布了 Visual Studio Code 项目:一个运行于 M ...
- Scrapy框架安装与使用(基于windows系统)
"人生苦短,我用python".最近了解到一个很好的Spider框架--Scrapy,自己就按着官方文档装了一下,出了些问题,在这里记录一下,免得忘记. Scrapy的安装是基于T ...
- 高校表白App-团队冲刺第十天
今天要做什么 做一个类似于淘宝的小云播报 做了什么 没有完全实现,轮转实现,功能没有 遇到的问题 遇到的问题好多啊,感觉写一天都写不完,我还是好好学习一下再重新写吧
- mac设置终端命令行别名alias(git、npm)
别名(alias)通常被用作对一串或单个命令的简称.懒人必备!当常用到命令行操作的时候,每次输入一长串命令,不厌其烦,自然想到了用简称代替.这里主要介绍两种mac设置别名alias的方式. mac 设 ...
- python编程面试题
# 实现需求为 注册.登录.查看昵称的功能 # def userN(): # username = input("请输入账号: \n") # password = ...
- 让Angular自定义组件支持form表单验证
Angular提供了一套非常强大的表单验证库(vue和react都需要第三方库的支持),可以非常方便简单实现web应用程序中的表单验证功能.但是如何让我们自定义的组件也支持验证呢? 我遇到一个需求是封 ...
- PAT乙级:1063 计算谱半径 (20分)
PAT乙级:1063 计算谱半径 (20分) 题干 在数学中,矩阵的"谱半径"是指其特征值的模集合的上确界.换言之,对于给定的 n 个复数空间的特征值 { a1+b1i,⋯,a** ...