4
29
2013
0

点分治

poj 1741 :男人八题23333

poj 2114:限制条件变成==k,该怎么弄怎么弄

省队互测题

BZOJ 1267 ←还没交

关于合并答案:

现在我们在点p,

p有各种孩子:b1,b2,b3,...,bn

首先可以得到他们的答案ans1...ansn

然后考虑经过p点的情形。

1)如果是要在限制Y下最大化XXXX(要满足可加性)

从一个子树出发,dfs出deepX情况下的最优解que[deep]

考虑这个最优解和前一颗线段树满足限制Y下的区间中的最优解的合并是否最优。

然后把这颗子树丢进线段树tree[deep](deep为关键字)

但是还有个单调性的做法:

当限制范围是L<=DIST<=R时

最大化tree[X]+que[Y] | L<=X+Y<=R,X,Y>=0

显然,如果X固定了,问题就变成求出que[L-X]到que[R-X]之间的最大值。

X单增,L-X,R-X也是单增,用单调队列维护就可以了。

nlogn->n  daze~啦啦啦啦啦比线段树好些多了23333

(某题解,差评!)

2)如果是要在限制条件Y下统计XXXX的个数

把条件转换成最好处理的,

利用单调性,类似统计逆序数的

统计一个子树下的答案,和所有子树下的答案……

然后该咋搞咋搞……

// 这只是一个简单的模板,在// ???填充代码……
#include <cstdio>
#include <cstdlib>
const int maxn = 100010;
const int maxm = 200010;
int n,l,r,mid;

struct node{
	int u,v,c;
	bool flag;
	node*next,*inv;
}E[maxm];int size = 0;

node * V[maxn];
int gravity[maxn];

int csize = 0;
int sum[maxn],balance[maxn];
bool inba[maxn];

int nsize = 0;

void callbalance(int root){
        nsize++;
	inba[root] = true;
	sum[root] = 1;
	for (node * it = V[root];it!=NULL; it = it->next){
		if (!t->flag){
			it->flag = it->inv->flag = true;
			callbalance(it->v);
			it->flag = it->inv->flag = false;
			sum[root]+=sum[it->v];
			balance[root] = (sum[it->v],balance[root]);
		}
	}
}

void callgravity(int root){
	csize = 0;
	memset(inba,0,sizeof(inba));
	node * p = V[root];

	callbalance(root);

	for(int i=1; i <= n; i++){
		if (inba[i]) balance[i] = max(nsize - sum[i] , balance[i]);
	}
	int mn = balance[root],int index = root;
	for(int i=1; i <= n; i++){
		if (inba[i]){ mn = balance[i]; index = i; }
	}

	gravity[root] = index;

	for (node * it = V[index];it!=NULL; it = it->next){
		if (!t->flag){
			it->flag = it->inv->flag = true;
			callbalance(it->v);
			it->flag = it->inv->flag = false;
		}
	}
}

int calc(int x){
	node * q = V[gravity[x]];
	int ans = 0;
	int rst = 0;
	for (node * it = q;it!=NULL;it = it->next){
		if (!t->flag){
			it->flag = true;
			it->inv->flag = true;
			ans = max(ans,calc(it->v));
			it->flag = false;
			it->inv->flag = false;
		}
	}
	// ???在这里合并。
	return max(ans,rst);
};
node* insert(int u,int v,int c,int g = 0,node *inv = NULL){
	node * p = &E[size++];
	p->u = u;p->v = v;p->c = c;p->g = g;p -> inv = inv?inv:insert(v,u,c,g,p);
	p->next = V[u];V[u]=p;
	return p;
}
int main(){
	scanf("%d%d%d",&n,&l,&r);
	for (int i = 0;i < n-1;i++)
	{
		int u,v,c;
		scanf("%d%d%d",&u,&v,&c);
		insert(u,v,c);
	};
	callgravity(1);

}
Category: 未分类 | Tags: 分治 | Read Count: 1056

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com