[2016-2017 ACM-ICPC CHINA-Final G]Pandaria
Posted StaroForgin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[2016-2017 ACM-ICPC CHINA-Final G]Pandaria相关的知识,希望对你有一定的参考价值。
Pandaria
题解
很恶心的一道题。
首先问从点
x
x
x开始走长度不超过
w
w
w的边很容易让人想到Kruskal重构树。
每次在最小生成树中加入边时,我们相当于新建一个节点,连接我们两点所在的子树的树根,作为它们的父亲,将边权设为其点权。
由于加入的边的边权是递增的,我们查询的点的父亲的点权肯定也是递增的。
该点能走不超过
w
w
w的边到达的节点,肯定是它点权不超过
w
w
w的深度最小的父亲的整棵子树内的所有节点。
我们查询能走到的出现次数最多的颜色,相当于查询该子树内哪种颜色出现次数最多。
显然,我们可以按dfs序将所有叶子节点排成一个序列,一个点子树内的点对应的区间在该序列上肯定是连续的。
由于只有叶子是我们原先就存在的节点,是有颜色的,我们只需要将叶子排成序列。
那么该子树内出现次数最多的颜色,也就是区间众数。
区间众数显然有我们经典的
O
(
n
n
)
O\\left(n\\sqrt{n}\\right)
O(nn)的分块做法 ,当然如果你会
O
(
n
)
−
O
(
1
)
O\\left(n\\right)-O\\left(1\\right)
O(n)−O(1)的
R
M
Q
RMQ
RMQ做法的也可以用,感觉跟四毛子算法有点像,但半群什么的我真的不会。
我们可以记录下每两个块之间出现次数最多的颜色是什么,显然这个颜色是可能成为众数的。
这个预处理是
O
(
n
2
S
)
O\\left(\\frac{n^2}{S}\\right)
O(Sn2),
S
S
S即块长,这样我们就可以
O
(
1
)
O(1)
O(1)求出整块的众数。
而散块内每个点都是可能成为众数,我们可以对于它们每个数都查询一下就行了。
为了查询散块内点的出现次数,我们需要先预处理出整块内每种颜色的前缀和,每次查询的时候还得先更新一下散块内每种颜色的出现次数。
显然,散块内只会有
S
S
S级别的颜色数,所以这块是
O
(
S
)
O\\left(S\\right)
O(S)的,而总共只会有
n
n
n中颜色,整块的预处理也是
O
(
n
2
S
)
O\\left(\\frac{n^2}{S}\\right)
O(Sn2)。
总时间复杂度 O ( n 2 S + q S + m log m ) ⩾ O ( n 2 q + m log m ) O\\left(\\frac{n^2}{S}+qS+m\\log\\,m\\right)\\geqslant O\\left(\\sqrt{n^2q}+m\\log\\,m\\right) O(Sn2+qS+mlogm)⩾O(n2q+mlogm)。
源码
#include<bits/stdc++.h>
using namespace std;
#define MAXN 100005
#define MAXM 200005
#define lowbit(x) (x&-x)
#define reg register
#define pb push_back
#define mkpr make_pair
#define fir first
#define sec second
#define lson (rt<<1)
#define rson (rt<<1|1)
typedef long long LL;
typedef unsigned long long uLL;
const int INF=0x3f3f3f3f;
const int inv2=499122177;
const int jzm=2333;
const int n1=400;
const int zero=10000;
const int orG=3,invG=332748118;
const double Pi=acos(-1.0);
const double eps=1e-5;
typedef pair<int,int> pii;
template<typename _T>
_T Fabs(_T x){return x<0?-x:x;}
template<typename _T>
void read(_T &x){
_T f=1;x=0;char s=getchar();
while(s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while('0'<=s&&s<='9'){x=(x<<3)+(x<<1)+(s^48);s=getchar();}
x*=f;
}
template<typename _T>
void print(_T x){putchar('\\n');while(x>9){putchar((x%10)|'0');x/=10;}putchar(x|'0');}
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
int add(int x,int y,int p){return x+y<p?x+y:x+y-p;}
void Add(int &x,int y,int p){x=add(x,y,p);}
int qkpow(int a,int s,int p){int t=1;while(s){if(s&1LL)t=1ll*a*t%p;a=1ll*a*a%p;s>>=1LL;}return t;}
const int M=MAXN/n1+5;
int T,n,m,q,head[MAXM],tot,fa[MAXM],idx,dfn[MAXM],rd[MAXM];
int f[MAXM][20],val[MAXM],col[MAXN],pre[MAXN];
int block[MAXN],L[M],R[M],mx[M][M],summ[M][MAXN],cnt[MAXN];
struct ming{int u,v,w;}s[MAXM];
bool cmp(ming x,ming y){return x.w<y.w;}
struct edge{int to,nxt;}e[MAXM<<1];
void addEdge(int u,int v){e[++tot]=(edge){v,head[u]};head[u]=tot;}
void makeSet(int x){for(int i=1;i<=x;i++)fa[i]=i;}
int findSet(int x){return fa[x]==x?x:fa[x]=findSet(fa[x]);}
void dosaka(int u,int fa){
f[u][0]=fa;dfn[u]=idx;if(u<=n)pre[idx]=u,idx++;
for(int i=1;i<19;i++)f[u][i]=f[f[u][i-1]][i-1];
for(int i=head[u];i;i=e[i].nxt)
if(e[i].to!=fa)dosaka(e[i].to,u);
rd[u]=idx-1;
}
inline int ask(int l,int r,int c){return summ[r][c]-summ[l-1][c];}
signed main(){
read(T);int tt=0;
while(T--){
read(n);read(m);makeSet(n);idx=n;int lans=0;
for(int i=1;i<=n;i++)read(col[i]);
for(int i=1;i<=m;i++)read(s[i].u),read(s[i].v),read(s[i].w);
sort(s+1,s+m+1,cmp);val[0]=INF;
for(int i=1;i<=m;i++){
int u=s[i].u,v=s[i].v,w=s[i].w;
if((u=findSet(u))==(v=findSet(v)))continue;
fa[u]=fa[v]=fa[++idx]=idx;val[idx]=w;
addEdge(idx,u);addEdge(idx,v);
}
int up=idx;idx=1;for(int i=up;i>0;i--)if(!dfn[i])dosaka(i,0);
for(int i=1;i<=n;i++)block[i]=(i+n1-1)/n1;
for(int i=1;i<=n;i++){if(!L[block[i]])L[block[i]]=i;R[block[i]]=i;}
for(int i=1;i<=block[n];i++){
for(int j=1;j<=n;j++)summ[i][j]=summ[i-1][j];
for(int j=L[i];j<=R[i];j++)summ[i][col[pre[j]]]++;
}
for(int i=1;i<=block[n];i++)
for(int j=i;j<=block[n];j++){
mx[i][j]=mx[i][j-1];int maxx=ask(i,j,mx[i][j]);
for(int k=L[j];k<=R[j];k++){
int tmp=ask(i,j,col[pre[k]]);
if(tmp>maxx||(tmp==maxx&&col2016-2017 ACM-ICPC CHINA-Final 个人题解
[2016-2017 ACM-ICPC CHINA-Final G]Pandaria
CF [2016-2017 ACM-ICPC CHINA-Final][GYM 101194 H] Great Cells
The 2018 ACM-ICPC China JiangSu Provincial Programming Contest(第六场)