BZOJ3572 [Hnoi2014]世界樹

3572:[Hnoi2014]世界樹

制限時間: 20秒   メモリ制限: 512メガバイトの
提出: 2625   解決: 1461
[ 送信 ] [ ステータス ] [ 議論 ]

説明

世界のツリーは、拡張その枝が全体の世界を形成し、非常に素晴らしい木です。ここでは、人種や生き物の多様性との生活、彼らは共同で、絶対公正かつ衡平な女神アリソンを信じて、自分の信条に、公正な世界は木が根本的な礎石の無限の、連続運転することができようにすることです。
木のフォーメーションを記述するために数学的モデルを使用することができます:世界のツリーは、民族的には1からnまでのn人種が番号が付けられ、地面に番号が1からnまでの集落に住んでいる、数はその集落の同じレース番号。いくつかの集落間の双方向の通りをリンクしている、道路の長さは1です。保証は互いに和解に達することができるすべてがツリー構造を形成するように接続手段、およびリングは発生しません。これは、2個の接続されたコロニーそれらの経路長との間の距離を定義し、例えば、道路の間の道路とB、BとCの間の決済が存在する場合、各道路の長さとが不可能を有するためリングは、とCとの間の水平距離は2です。
公正性の理由から、私は今年、世界樹の王は、認可メートル一時的な集落の手順で、[i]のレースが必要です。人種X(レース番号のX)、もしYレースのための手順の最近仮ルールに離れレースから、XのY手順で支配される(IF(yはコロニーの数は、手順の点で)より数yが最小仮手続きである、請求同一の決済の手順に一時的距離)。
手順の暫定規則で各年の任務は毎年の完了はどのように多くの(集落の手続きのルールも管理手順で受け付けます)レース管理されます後に王は、Q-年間で、知っていただきたいと思います。今、あなたのために知られている霊長類の知恵にこのタスク:プログラム猿。タスクバーを完了するために、王を助けてください。

入力

最初の行の正の整数n、レースの世界で木の数。
次NL行は、各列2つの正の整数x、yは、xはコロニーの間で決済を表し、yは二重長さ1は
道路。次に、正の整数qの挙動は、王は尋ねた年の数を表します。
次Qブロック、各2行:
私が1mの正の整数を作用最初のブロック[i]は、許可の手順におけるi番目の仮の数を表します。
i番目のブロックMの2行目[i]は正の整数H [L]、H [2 ]、...、H [mは[I]、 コロニー数を仮手順で許可されているように、互いに異なる保証(発現しました)。

出力

出力線Q、I mの挙動を含む[i]は整数、j番目の行が(j = 1,2 ... ,, M [i])と認可集落のH [J]ののi番目の数を示しますレース運営の手続きの暫定ルールの数。

サンプル入力

10
2 1
3 2
4 3
5 4
6 1
7 3
8 3
9 4
10 1
5
2
6 1
5
2 7 3 6 9
1
8
4
8 7 10 3
5
2 9 3 5 8

サンプル出力

1 9
3 1 4 1 1
10
1 1 3 5
4 1 3 1 1

ヒント

N <= 300000、Q <= 300000、M [1] + M [2] + ... + M [Q] <= 300000

ソース

[ 送信 ] [ ステータス ] [ 議論 ]

HOME へ戻ります

問題の解決策

同じタイトルの仮想ツリーでは、この質問は明らかに最初のみに関連する重要なポイントの複雑さに、仮想ツリーを構築し、することです。明らかに、分類プロセスが議論されています。

私たちは、仮想ツリーに再びDFSに属する各ノードのポイントを与えます。その後、我々だけの統計ツリーポイントは(以下、統計上のツリー内の仮想点が考慮されません)仮想ではありません。

このエッジは、元のツリーノードの寄与に相当失う、各エッジ仮想ツリーを考えます。

  1. 2つのエンドポイントは、ここで同じノードに属している場合は、限りの貢献などを再度追加することができます。
  2. 2つの点が同じノードに属していない場合は、明らか中間境界点があるでしょう、そして、境界点乗算は半ばを特定し、その両側の寄与を計算します。

明らかに、この方法の寄与を考慮に含まれるノードを(サブツリーが一つでもノードを見て)、議論する必要はありません。また、我々はグラム・アレイは、これらが、サブツリーが自分の貢献に直接ノードの数を決定することができます議論する必要はないことを示して覚えておく必要があります。限りサイズを設定した初期値として、上記の一部の質問プットを議論削除することができます。

時間複雑\(O((N + \ SUM mの)\ n型ログ)\) この問題は何もできない、他の人のコードについて、名前の変更を掲載しました。

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 300011;
const int MAXM = 600011;
int n,tot,next[MAXM],to[MAXM],head[MAXN],dfn[MAXN],size[MAXN],dep[MAXN],f[MAXN][19];
int m,a[MAXN],b[MAXN],belong[MAXN],stack[MAXN],top,g[MAXN],ans[MAXN],cnt,c[MAXN];
inline void add_edge(int x,int y){ if(x==0 || x==y) return ; next[++tot]=head[x]; head[x]=tot; to[tot]=y; }
inline bool cmp(int x,int y){ return dfn[x]<dfn[y]; }
inline int read(){
    int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar();
    if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w;
}
 
inline void init(int x,int fa){
    size[x]=1; dfn[x]=++tot;
    for(int i=head[x];i;i=next[i]) {
        int v=to[i]; if(v==fa) continue;
        f[v][0]=x; dep[v]=dep[x]+1;
        init(v,x); size[x]+=size[v];
    }
}
 
inline int lca(int x,int y){
    if(dep[x]<dep[y]) swap(x,y); int t=0; while((1<<t)<=dep[x]) t++; t--;
    for(int i=t;i>=0;i--) if(dep[x]-(1<<i)>=dep[y]) x=f[x][i]; if(x==y) return x;
    for(int i=t;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0];
}
 
inline int dis(int x,int y){ return dep[x]+dep[y]-dep[lca(x,y)]*2; }
 
inline void dfs_down(int x,int fa){
    int d1,d2; g[x]=size[x]; c[++cnt]=x;
    for(int i=head[x];i;i=next[i]) {
        int v=to[i]; if(v==fa) continue;
        dfs_down(v,x);
        if(belong[x]==0) { belong[x]=belong[v]; continue; }//注意不要出0了
        d1=dis(belong[v],x); d2=dis(belong[x],x);
        if(d1<d2 || (d1==d2 && belong[v]<belong[x])) belong[x]=belong[v];
    }
}
 
inline void dfs_up(int x,int fa){
    int d1,d2;
    for(int i=head[x];i;i=next[i]) {
        int v=to[i]; if(v==fa) continue;
        d1=dis(belong[v],v); d2=dis(belong[x],v);
        if(d1>d2 || (d1==d2 && belong[v]>belong[x])) belong[v]=belong[x];
        //必须先划分再下传!不然会有问题!
        dfs_up(v,x); 
    }
}
 
inline void solve(int fa,int u){//讨论(fa,u)这条边
    int son=u,mid=u,nex,d1,d2;
    for(int i=18;i>=0;i--)//son是fa到u的路径上的第一个节点,也就是一个原树上的儿子节点
        if(dep[son]-(1<<i)>dep[fa])
            son=f[son][i];
 
    g[fa]-=size[son];//减去加入讨论的部分,保留仍未讨论的部分,是size而不是g!
    if(belong[fa]==belong[u]) { ans[belong[fa]]+=size[son]-size[u]; return ; }
    for(int i=18;i>=0;i--) {//寻找分界点
        nex=f[mid][i]; if(dep[nex]<=dep[fa]) continue;
        d1=dis(nex,belong[fa]); d2=dis(nex,belong[u]);
        if(d1>d2 || (d1==d2 && belong[u]<belong[fa])) mid=nex;
    }
    ans[belong[fa]]+=size[son]-size[mid];
    ans[belong[u]]+=size[mid]-size[u];
}
 
inline void build(){
    m=read(); for(int i=1;i<=m;i++) a[i]=read(),b[i]=a[i];
    for(int i=1;i<=m;i++) belong[a[i]]=a[i];
    top=tot=cnt=0; sort(a+1,a+m+1,cmp); if(belong[1]!=1) stack[++top]=1;
    int LCA;
    for(int i=1;i<=m;i++) {
        if(top==0) { stack[++top]=a[i]; continue; }
        LCA=lca(stack[top],a[i]);
        while(1) {
            if(dep[stack[top-1]]<=dep[LCA]) {
                add_edge(LCA,stack[top]); top--;
                if(stack[top]!=LCA) stack[++top]=LCA;
                break;
            }
            add_edge(stack[top-1],stack[top]);
            top--;
        }
        if(stack[top]!=a[i]) stack[++top]=a[i];
    }
    while(top>1) add_edge(stack[top-1],stack[top]),top--; top--; //记得把剩下的连完边!
 
    dfs_down(1,0);
    dfs_up(1,0);
 
    //对于虚树上的每一条边进行考虑
    for(int i=1;i<=cnt;i++)
        for(int j=head[c[i]];j;j=next[j])
            solve(c[i],to[j]);
 
    for(int i=1;i<=cnt;i++) ans[belong[c[i]]]+=g[c[i]];
    for(int i=1;i<=m;i++) printf("%d ",ans[b[i]]); puts("");
    for(int i=1;i<=cnt;i++) ans[c[i]]=head[c[i]]=g[c[i]]=belong[c[i]]=0;//需要清空的是所有!不只是m
}

int main()
{
    n=read(); int x,y;
    for(int i=1;i<n;i++) { x=read(); y=read(); add_edge(x,y); add_edge(y,x); }
    tot=0; init(1,0); tot=0; memset(head,0,sizeof(head));
    for(int j=1;j<=18;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1];
    int q=read();
    while(q--) build();
    return 0;
}

おすすめ

転載: www.cnblogs.com/autoint/p/11057381.html
おすすめ