Jzoj5462【NOIP2017提高A组冲刺11.8】证书

Pulumi生活在P城的角落,而他的朋友们gjdy,oyski,tutuwai等等生活在P城的靠中心位置。
P城很大,但它拥有优秀的城市结构,同时P城重视文化教育的发展,P城共有n个学校,校与校之间共建立了n-1条交通线路,且两所学校之间存在唯一的连通路径。
P城常常举行各种类型的评比活动,为了节约资金,最终将给某一条路径上的所有学校颁发证书。为了便于描述我们记一次评比活动的结果为(ui,vi,zi)表示路径(ui,vi)上的所有学校获得一个类型为zi的证书。
一个学校若为Zmax类型的学校,则表示它在Zmax类型下的证书数量最多(如果有相同数量的类型,取类型标号最小一个)。

Pulumi收集了本年度所有的评比活动结果,共m次。他很感兴趣所有学校的类型,以了解他朋友们学校的状况,现在他忙于出题,把这个任务交给了你。

本来以为区间众数只能莫队做了呢结果发现可以用线段树合并

考场上以为区间众数不满足区间价法(对于普通线段树确实不满足,但是这里应该用权值线段树)

写了启发式map合并结果错一堆

首先输出答案没有换行(这已经没分了)

第二dfs时候爆栈了

而且一个地方没有判零

好吧说一下正解:

我们对于一条路径,在端点处打上两个+1,在lca打上一个-1,在f[lca]打上一个-1

那么答案就是整个子树的众数

我们开一个map一个set,一个代表的是size,即size[x][k]表示k在x的子树中出现了几次

set存一个pair,这个pair的first代表的是size[x][k]的值,second是k,整体按照first作为优先级

set其实就是用来统计答案的,合并的是map

卡栈?参考几天前那个什么游戏那篇的

居然速度还不错看来O(nlg^2n)还是挺可靠的(还不是因为自己开了O3

#pragma GCC optimize("O3")
#pragma G++ optimize("O3")
#include<map>
#include<set>
#include<vector>
#include<stdio.h>
#include<string.h>
#include<stdlib.h> 
#include<algorithm>
#define N 120010
using namespace std;
struct pr{ int x,y; };
extern int main2(void) __asm__ ("main2");  
inline bool operator< (pr a,pr b){ return a.x==b.x?a.y<b.y:a.x>b.x; }
vector<int> G[N]; set<pr> r[N];
vector<pr> w[N]; map<int,int> s[N];
int sz[N],top[N],f[N],son[N],rt[N];
int n,m,d[N],A[N];
void dfs(int x,int p){
	f[x]=p; sz[x]=1; d[x]=d[p]+1;
	for(int v,i=0;i<G[x].size();++i)
		if((v=G[x][i])!=p){
			dfs(v,x);
			sz[x]+=sz[v];
			if(sz[v]>sz[son[x]]) son[x]=v;
		}
}
void dijk(int x,int p){
	top[x]=p;
	if(son[x]) dijk(son[x],p);
	for(int v,i=0;i<G[x].size();++i)
		if((v=G[x][i])!=f[x] && v!=son[x]) dijk(v,v);
}
inline int gLca(int x,int y,int c){
	w[x].push_back((pr){c,1});
	w[y].push_back((pr){c,1});
	for(;top[x]!=top[y];y=f[top[y]])
		if(d[top[x]]>d[top[y]]) swap(x,y);
	if(d[x]>d[y]) x=y;
	w[x].push_back((pr){c,-1});
	w[f[x]].push_back((pr){c,-1});
	return x;
}
inline void merge(int x,int v){
	for(map<int,int>::iterator it=s[v].begin();it!=s[v].end();++it){
		int val=it->first,siz=s[x][val],ds=it->second;
		if(siz==0) r[x].insert((pr){ds,val});
		else { r[x].erase((pr){siz,val}); if(siz+ds) r[x].insert((pr){siz+ds,val}); }
		s[x][val]+=ds;
	}
	s[v].clear(); r[v].clear();
}
void cal(int x){
	if(son[x]){
		cal(son[x]); 
		rt[x]=rt[son[x]];
	} else rt[x]=x;
	for(int v,i=0;i<G[x].size();++i)
		if((v=G[x][i])!=f[x] && v!=son[x]) {
			cal(v);
			merge(rt[x],rt[v]);
		}
	int r1=rt[x];
	for(vector<pr>::iterator it=w[x].begin();it!=w[x].end();++it){
		int val=it->x,siz=s[r1][val];
		if(siz==0) r[r1].insert((pr){it->y,val});
		else { r[r1].erase((pr){siz,val}); r[r1].insert((pr){siz+it->y,val}); }
		s[r1][val]+=it->y;
	}
	if(r[r1].empty()||r[r1].begin()->x<=0) A[x]=0;
	else A[x]=r[r1].begin()->y;
}
int main2(){
	freopen("certif.in","r",stdin);
	freopen("certif.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int x,y,i=1;i<n;++i){
		scanf("%d%d",&x,&y);
		G[x].push_back(y);
		G[y].push_back(x);
	}
	dfs(1,0); dijk(1,1);
	for(int x,y,c;m--;){
		scanf("%d%d%d",&x,&y,&c);
		gLca(x,y,c);
	}
	cal(1);
	for(int i=1;i<=n;++i) printf("%d\n",A[i]);
	exit(0);
}
int main(){
	int size = 256 << 20;  // 256Mb  
    	char *p = (char *)malloc(size) + size;  
    	__asm__ __volatile__(  
        "movq  %0, %%rsp\n"  
        "pushq $exit\n"   
        "jmp main2\n"  
        :: "r"(p)); 
}


posted @ 2017-11-16 19:32  扩展的灰(Extended_Ash)  阅读(98)  评论(0编辑  收藏  举报