[二维偏序]
AC自动机
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <set>
#include <map>
#define maxn 200010
using namespace std;
int n, p[maxn], c[maxn];
map<int, int> M[maxn];
typedef map<int, int>::iterator mit;
int fail[maxn];
queue<int> Q;
const int root = 0;
int main(){
freopen("tree.in", "r", stdin);
freopen("tree.out", "w", stdout);
scanf("%d", &n);
for(int i = 1; i <= n; i ++) scanf("%d", &p[i]);
for(int i = 1; i <= n; i ++) scanf("%d", &c[i]);
for(int i = 1; i <= n; i ++)
M[p[i]][c[i]] = i;
memset(fail, 0, sizeof fail);
for(mit it = M[root].begin(); it != M[root].end(); it ++)
Q.push(it->second);
while(!Q.empty()){
int u = Q.front(); Q.pop();
for(mit it = M[u].begin(); it != M[u].end(); it ++){
int tmp = it->second, now = fail[u];
while(now && !M[now].count(it->first))
now = fail[now];
if(M[now].count(it->first))
fail[tmp] = M[now][it->first];
Q.push(tmp);
}
}
for(int i = 1; i <= n; i ++)
printf("%d ", fail[i]);
return 0;
}
有一个俱乐部打算把他们的成员分成多个组。
成员i 有一个责任度ri 个年龄ai,一个组是一个非空的子集且组内有一个组长,组长一定是这个组内责任度最高的人(责任度不小于其他任意成员), 而且他的年龄和其他成员的绝对值不能超过k。
有一些成员原本就是好基友所以他们希望分在同一个组,他们都希望他们的组越大越好。现在会给一些询问(x,y),询问从所有成员中分出来一个最大的组包含x 和y(x,y 可能是组长),这个组最大是多少人?
算出每一个人的贡献,排序+线段树。二维偏序
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#define maxn 500010
using namespace std;
int n, k, pos[maxn];
struct operation{int r, a, p, ans;}opt[maxn];
bool cmpa(const operation& a, const operation& b){return a.a < b.a;}
bool cmpr(const operation& a, const operation& b){return a.r > b.r;}
int ans[maxn];
int L[maxn], R[maxn], h[maxn], cnt;
#define lc id << 1
#define rc id << 1 | 1
void build(int id, int l, int r){
L[id] = l, R[id] = r;
if(l == r)return;
int mid = l + r >> 1;
build(lc, l, mid);
build(rc, mid+1, r);
}
namespace Seg1{
int t[maxn];
void update(int id, int pos, int val){
t[id] += val;
if(L[id] == R[id])return;
int mid = L[id] + R[id] >> 1;
if(pos <= mid)update(lc, pos, val);
else update(rc, pos, val);
}
int ask(int id, int l, int r){
if(L[id] == l && R[id] == r)return t[id];
int mid = L[id] + R[id] >> 1;
if(r <= mid)return ask(lc, l, r);
if(l > mid) return ask(rc, l, r);
return ask(lc, l, mid) + ask(rc, mid+1, r);
}
void work(){
sort(opt + 1, opt + 1 + n, cmpa);
cnt = 0;
for(int i = 1; i <= n; i ++)h[i] = opt[i].r;
sort(h + 1, h + 1 + n);
cnt = unique(h + 1, h + 1 + n) - h - 1;
for(int i = 1; i <= n; i ++)
opt[i].r = lower_bound(h + 1, h + 1 + cnt, opt[i].r) - h;
int l = 1, r = 0;
for(int i = 1; i <= n; i ++){
for(; l <= n && opt[l].a + k < opt[i].a; l ++) update(1, opt[l].r, -1);
for(; r < n && opt[i].a + k >= opt[r + 1].a; r ++) update(1, opt[r + 1].r, 1);
opt[i].ans = ask(1, 1, opt[i].r);
}
}
}
namespace Seg2{
int t[maxn], p[maxn], fr[maxn], to[maxn];
struct query{
int x, y, r, id;
bool operator<(const query& k)const{return r > k.r;}
}q[maxn];
void update(int id, int pos, int val){
t[id] = max(t[id], val);
if(L[id] == R[id])return;
int mid = L[id] + R[id] >> 1;
if(pos <= mid)update(lc, pos, val);
else update(rc, pos, val);
}
int ask(int id, int l, int r){
if(l > r)return -1;
if(L[id] == l && R[id] == r)return t[id];
int mid = L[id] + R[id] >> 1;
if(r <= mid)return ask(lc, l, r);
if(l > mid) return ask(rc, l, r);
return max(ask(lc, l, mid), ask(rc, mid+1, r));
}
void work(){
memset(t, -1, sizeof t);
cnt = n;
for(int i = 1; i <= n; i ++) h[i] = opt[i].a;
sort(h + 1, h + 1 + n);
cnt = unique(h + 1, h + 1 + n) - h - 1;
build(1, 1, cnt);
for(int i = 1; i <= n; i ++){
int f = lower_bound(h + 1, h + 1 + cnt, opt[i].a - k) - h;
int t = upper_bound(h + 1, h + 1 + cnt, opt[i].a + k) - h;
t = min(t, cnt);
while(opt[i].a + k < h[t]) t --;
fr[opt[i].p] = f, to[opt[i].p] = t;
}
sort(opt + 1, opt + 1 + n, cmpr);
for(int i = 1; i <= n; i ++) pos[opt[i].p] = i;
for(int i = 1; i <= n; i ++)
p[i] = lower_bound(h + 1, h + 1 + cnt, opt[i].a) - h;
int test, x, y;
scanf("%d", &test);
for(int i = 1; i <= test; i ++){
scanf("%d%d", &x, &y);
q[i].x = x, q[i].y = y;
x = pos[x], y = pos[y];
q[i].r = max(opt[x].r, opt[y].r), q[i].id = i;
}
sort(q + 1, q + 1 + test);
int it = 1;
memset(ans, -1, sizeof ans);
for(int i = 1; i <= test; i ++){
for(; it <= n && opt[it].r >= q[i].r; it ++)
update(1, p[it], opt[it].ans);
x = q[i].x, y = q[i].y;
int dw = max(fr[x], fr[y]);
int up = min(to[x], to[y]);
ans[q[i].id] = ask(1, dw, up);
}
for(int i = 1; i <= test; i ++)
printf("%d\n", ans[i]);
}
}
int main(){
freopen("groups.in", "r", stdin);
freopen("groups.out", "w", stdout);
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i ++)scanf("%d", &opt[i].r);
for(int i = 1; i <= n; i ++)scanf("%d", &opt[i].a);
for(int i = 1; i <= n; i ++)opt[i].p = i;
build(1, 1, n);
Seg1::work();
Seg2::work();
return 0;
}
给时光以生命,而不是给生命以时光。

浙公网安备 33010602011771号