[二维偏序]

 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;
}

  

posted @ 2016-04-18 18:55  _Horizon  阅读(203)  评论(0)    收藏  举报