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

来源:互联网 发布:查看守望先锋数据 编辑:程序博客网 时间:2024/05/22 06:05
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 120010using 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)); }


原创粉丝点击