贪心思想。将a排序后,对于每一个a,找到对应的删除m个后最小的b,每次更新答案即可。

如何删除才是合法并且最优的?首先,对于排了序的a,第$i$个那么之前就应该删除前$i-1$个a对应的b。剩下$m-i+1$可以删,那么在剩下的b中查找第$m-i+2$小即可。每次做完就删除当前a对应的b。

注意离散化。

还有数组不要开大了....

#include<bits/stdc++.h>
#define LL long long
using namespace std; void read(int &x) {
x = ; int t = ; char ch = getchar();
while(ch > '' || ch < '') { if(ch == '-') t = -; ch = getchar(); }
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
x = x * t;
} int a[], b[], n, m; struct Node {
int a, b;
int ida, idb;
} mat[];
bool cmp(Node a, Node b) { if(a.a == b.a) return a.b < b.b; return a.a < b.a; } int siz[], val[]; void modify(int nd, int l, int r, int pos, int d) {
if(l == r) {
siz[nd] += d;
return ;
}
int mid = (l + r) >> ;
if(pos <= mid) modify(nd << , l, mid, pos, d);
else modify(nd << | , mid + , r, pos, d);
siz[nd] = siz[nd << ] + siz[nd << | ];
} int query(int nd, int l, int r, int pos) {
if(l == r) return val[l];
int mid = (l + r) >> ;
if(pos <= siz[nd << ]) return query(nd << , l, mid, pos);
else return query(nd << | , mid + , r, pos - siz[nd << ]);
} int pos[];
void work() {
sort(b + , b + + n);
int q = unique(b + , b + + n) - b - ; memset(siz, , sizeof(siz));
sort(mat + , mat + + n, cmp);
for(int i = ; i <= n; i ++) {
pos[i] = lower_bound(b + , b + + q, mat[i].b) - b;
val[pos[i]] = mat[i].b;
modify(, , q, pos[i], );
} LL ans = ;
int r = min(mat[].b, query(, , q, m + ));
ans = 1ll * mat[].a * r;
for(int i = ; i <= m; i ++) {
modify(, , q, pos[i], -);
int res = m - i + ;
r = query(, , q, res);
if(mat[i + ].b < r) r = mat[i + ].b;
LL now = 1ll * mat[i + ].a * r;
ans = max(ans, now);
} printf("%lld\n", ans);
} int main() {
freopen("d.in", "r", stdin);
freopen("d.out", "w", stdout);
int T;
scanf("%d", &T);
while(T --) {
read(n); read(m);
for(int i = ; i <= n; i ++) {
read(mat[i].a); read(mat[i].b);
b[i] = mat[i].b;
}
work();
}
return ;
}

依旧是数据结构。我们发现,对于一个点集,它们一定有一个lca,而满足包含所有点的最小点集就是所有点到这个lca的链上的所有点。再加上题目要求最小的$abs(a[u]-r)$,就是用每条链上r的前驱和后驱来更新答案。

用主席树维护即可。每个结点的版本是由它的父亲结点转移过来。这样做查询的时候直接取出当前结点和lca的父亲结点的版本即可。

关于这个前驱和后驱的计算可以学习一下。

#include<bits/stdc++.h>
#define LL long long
using namespace std; const int maxn = 1e9; void read(int &x) {
x = ; int t = ; char ch = getchar();
while(ch > '' || ch < '') { if(ch == '-') t = -; ch = getchar(); }
while(ch >= '' && ch <= '') {
x = x * + ch - '';
ch = getchar();
}
x = x * t;
} int n, q, type; struct Node {
int v, nex;
Node(int v = , int nex = ) :
v(v), nex(nex) { }
} Edge[]; int h[], stot;
void add(int u, int v) {
Edge[++stot] = Node(v, h[u]);
h[u] = stot;
} int sum[*], ls[*], rs[*], tail;
inline int newnode(int x) {
sum[++tail] = sum[x];
ls[tail] = ls[x]; rs[tail] = rs[x];
return tail;
} inline void update(int nd) {
sum[nd] = sum[ls[nd]] + sum[rs[nd]];
} int insert(int nd, int l, int r, LL pos) {
nd = newnode(nd);
sum[nd] ++;
if(l == r) return nd;
int mid = (l + r) >> ;
if(pos <= mid) ls[nd] = insert(ls[nd], l, mid, pos);
else rs[nd] = insert(rs[nd], mid + , r, pos);
update(nd);
return nd;
} int queryl(int nd1, int nd2, int l, int r, int pos) {
if(sum[nd1] == sum[nd2]) return ;///这个结点下面没有新的点
if(l == r) return l;
int mid = (l + r) >> ;
if(pos <= mid) return queryl(ls[nd1], ls[nd2], l, mid, pos);
else {
int tmp = queryl(rs[nd1], rs[nd2], mid + , r, pos);////尽量往靠近pos的地方走
if(tmp) return tmp;///如果走不到就尽量往mid走
else return queryl(ls[nd1], ls[nd2], l, mid, mid);
}
} int queryr(int nd1, int nd2, int l, int r, int pos) {
if(sum[nd1] == sum[nd2]) return ;
if(l == r) return l;
int mid = (l + r) >> ;
if(pos > mid) return queryr(rs[nd1], rs[nd2], mid + , r, pos);
else {
int tmp = queryr(ls[nd1], ls[nd2], l, mid, pos);
if(tmp) return tmp;
else return queryr(rs[nd1], rs[nd2], mid + , r, mid);
}
} int dep[], jum[][];
int lca(int u, int v) {
if(dep[u] < dep[v]) swap(u, v);
int t = dep[u] - dep[v];
for(int p = ; t; t >>= , p ++)
if(t & ) u = jum[u][p];
if(u == v) return u;
for(int p = ; p >= ; p --)
if(jum[u][p] != jum[v][p]) u = jum[u][p], v = jum[v][p];
return jum[u][];
} int rt[], a[];
void dfs(int u, int f) {
jum[u][] = f;
for(int i = ; i < ; i ++)
jum[u][i] = jum[jum[u][i - ]][i - ];
dep[u] = dep[f] + ;
rt[u] = insert(rt[f], , maxn, a[u]);
for(int i = h[u]; i; i = Edge[i].nex) {
int v = Edge[i].v;
if(v == f) continue;
dfs(v, u);
}
} int x[], p[];
int main() {
freopen("e.in", "r", stdin);
freopen("e.out", "w", stdout);
scanf("%d%d%d", &n, &q, &type);
for(int i = ; i <= n; i ++) read(a[i]);
for(int i = ; i < n; i ++) {
int u, v;
read(u); read(v);
add(u, v); add(v, u);
}
dfs(, );
int lastans = ;
for(int i = ; i <= q; i ++) {
int r, k;
scanf("%d%d", &r, &k);
for(int j = ; j <= k; j ++) {
read(x[j]);
p[j] = (x[j] - + lastans * type) % n + ;
}
int l = p[];
for(int j = ; j <= k; j ++)
l = lca(l, p[j]);
l = jum[l][];
int res = maxn, tmp;
for(int j = ; j <= k; j ++) {
tmp = queryl(rt[l], rt[p[j]], , maxn, r);
if(tmp && r - tmp < res) res = r - tmp;
tmp = queryr(rt[l], rt[p[j]], , maxn, r);
if(tmp && tmp - r < res) res = tmp - r;
}
printf("%d\n", res);
lastans = res;
}
return ;
}

【10.10校内测试】【线段树维护第k小+删除】【lca+主席树维护前驱后驱】的更多相关文章

  1. PAT天梯赛练习题 L3-002. 堆栈(线段树查询第K大值或主席树)

    L3-002. 堆栈 时间限制 200 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 陈越 大家都知道“堆栈”是一种“先进后出”的线性结构,基本操作有 ...

  2. HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)

    题意:给一个数组,每次给 l ,r, p, k,问区间 [l, r] 的数与 p 作差的绝对值的第 k 小,这个绝对值是多少 分析:首先我们先分析单次查询怎么做: 题目给出的数据与多次查询已经在提示着 ...

  3. SPOJ 10628. Count on a tree (树上第k大,LCA+主席树)

    10628. Count on a tree Problem code: COT You are given a tree with N nodes.The tree nodes are number ...

  4. COGS 930. [河南省队2012] 找第k小的数 主席树

    主席树裸板子 #include<cstdio> #include<iostream> #include<algorithm> #define MAXN 100005 ...

  5. [xdoj1216]子树第k小(dfs序+主席树)

    解题关键:dfs序将树映射到区间,然后主席树求区间第k小,为模板题. #pragma comment(linker, "/STACK:1024000000,1024000000") ...

  6. 【9.22校内测试】【可持久化并查集(主席树实现)】【DP】【点双联通分量/割点】

    1 build1.1 Description从前有一个王国,里面有n 座城市,一开始两两不连通.现在国王将进行m 次命令,命令可能有两种,一种是在u 和v 之间修建道路,另一种是询问在第u 次命令执行 ...

  7. LCA+主席树 (求树上路径点权第k大)

      SPOJ 10628. Count on a tree (树上第k大,LCA+主席树) 10628. Count on a tree Problem code: COT You are given ...

  8. 【SPOJ】10628. Count on a tree(lca+主席树+dfs序)

    http://www.spoj.com/problems/COT/ (速度很快,排到了rank6) 这题让我明白了人生T_T 我知道我为什么那么sb了. 调试一早上都在想人生. 唉. 太弱. 太弱. ...

  9. 【bzoj3123】[Sdoi2013]森林 倍增LCA+主席树+启发式合并

    题目描述 输入 第一行包含一个正整数testcase,表示当前测试数据的测试点编号.保证1≤testcase≤20. 第二行包含三个整数N,M,T,分别表示节点数.初始边数.操作数.第三行包含N个非负 ...

随机推荐

  1. Python time()方法

    from:http://www.runoob.com/python/att-time-time.html 描述 Python time time() 返回当前时间的时间戳(1970纪元后经过的浮点秒数 ...

  2. ClientDataset 三层 var and out arguments must match parameter

    ​​​将Delphi升级到10.1.2后,从客户端传ClientDataset的Delta数据到服务端程序时,出现var and out arguments must match parameter错 ...

  3. js中字符串的常用方法

    一.普通方法 1.字符方法 动态方法:1.str.charAt(index);  返回子字符串,index为字符串下标,index取值范围[0,str.length-1] 动态方法:2.str.cha ...

  4. .NET 4.5 Task异步编程学习资料

    参考资料: 1. http://www.cnblogs.com/heyuquan/archive/2013/04/18/3028044.html

  5. 使用html+css+js实现日历与定时器,看看今天的日期和今天剩余的时间。

    使用html+css+js实现日历与定时器,看看今天的日期和今天剩余的时间. 效果图: 哎,今天就又这么过去了,过的可真快 . 代码如下,复制即可使用: <!DOCTYPE html> & ...

  6. js中的call,apply,bind区别

    在JavaScript中,call.apply和bind是Function对象自带的三个方法,这三个方法的主要作用是改变函数中的this指向. call.apply.bind方法的共同点和区别:app ...

  7. 为通过 ATS 检测 Tomcat 完全 TLS v1.2、完全正向加密及其结果检验

    2017 年起 app store 要求 app 对接的服务器支持 TLS v1.2,否则 ats 检测不予通过.有点强制推 TLS v1.2 的意味.本文介绍如何使 tomcat 强制执行 TLS ...

  8. hdu 5943(素数间隔+二分图匹配)

    Kingdom of Obsession Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Oth ...

  9. Error_code: 1594(mysql 5617)主从同步报错

    报错信息 2017-09-05 09:37:22 7425 [ERROR] Slave SQL: Relay log read failure: Could not parse relay log e ...

  10. 国内最火的 HTML、CSS、JavaScript 开源项目 Top 榜,你知多少?

    对于开发者而言,想要着手前端开发,HTML.CSS 和 JavaScript 是三项必备的基础技能.而如何事半功倍地掌握好这些知识?通过了解当下火热的开源项目不乏为最佳学习姿势.本文盘点国内评分最高且 ...