1. 程式人生 > 實用技巧 >BZOJ3872. [Poi2014]Ant colony

BZOJ3872. [Poi2014]Ant colony

Description

There is an entrance to the ant hill in every chamber with only one corridor leading into (or out of) it. At each entry, there are g groups of m1,m2,...,mg ants respectively. These groups will enter the ant hill one after another, each successive group entering once there are no ants inside. Inside the hill, the ants explore it in the following way:
Upon entering a chamber with d outgoing corridors yet unexplored by the group, the group divides into d groups of equal size. Each newly created group follows one of the d corridors. If d=0, then the group exits the ant hill. If the ants cannot divide into equal groups, then the stronger ants eat the weaker until a perfect division is possible. Note that such a division is always possible since eventually the number of ants drops down to zero. Nothing can stop the ants from allowing divisibility - in particular, an ant can eat itself, and the last one remaining will do so if the group is smaller than d.
The following figure depicts m ants upon entering a chamber with three outgoing unexplored corridors, dividing themselves into three (equal) groups of floor(m/3) ants each. A hungry anteater dug into one of the corridors and can now eat all the ants passing through it. However, just like the ants, the anteater is very picky when it comes to numbers. It will devour a passing group if and only if it consists of exactly k ants. We want to know how many ants the anteater will eat.
給定一棵有n個節點的樹。在每個葉子節點,有g群螞蟻要從外面進來,其中第i群有m[i]只螞蟻。這些螞蟻會相繼進入樹中,而且要保證每一時刻每個節點最多隻有一群螞蟻。這些螞蟻會按以下方式前進: ·在即將離開某個度數為d+1的點時,該群螞蟻有d個方向還沒有走過,這群螞蟻就會分裂成d群,每群數量都相等。如果d=0,那麼螞蟻會離開這棵樹。 ·如果螞蟻不能等分,那麼螞蟻之間會互相吞噬,直到可以等分為止,即一群螞蟻有m只,要分成d組,每組將會有floor(m/d)只,如下圖。 一隻飢餓的食蟻獸埋伏在一條邊上,如果有一群螞蟻通過這條邊,並且數量恰為k只,它就會吞掉這群螞蟻。請計算一共有多少隻螞蟻會被吞掉。

Input

The first line of the standard input contains three integers n, g, k (2<=n,g<=1000000, 1<=k<=10^9), separated by single spaces. These specify the number of chambers, the number of ant groups and the number of ants the anteater devours at once. The chambers are numbered from 1 to n. The second line contains g integers m[1],m[2],...,m[g](1<=m[i]<=10^9), separated by single spaces, where m[i] gives the number of ants in the i-th group at every entrance to the ant hill. The n-1 lines that follow describe the corridors within the ant hill; the i-th such line contains two integers a[i],b[i] (1<=a[i],b[i]<=n), separated by a single space, that indicate that the chambers no.a[i] and b[i] are linked by a corridor. The anteater has dug into the corridor that appears first on input. 第一行包含三個整數n,g,k,表示點數、螞蟻群數以及k。 第二行包含g個整數m[1],m[2],...,m[g],表示每群螞蟻中螞蟻的數量。 接下來n-1行每行兩個整數,表示一條邊,食蟻獸埋伏在輸入的第一條邊上。

Output

Your program should print to the standard output a single line containing a single integer: the number of ants eaten by the anteater. 一個整數,即食蟻獸能吃掉的螞蟻的數量。

Sample Input

7 5 3
3 4 1 9 11
1 2
1 4
4 3
4 5
4 6
6 7

Sample Output

21

Hint

Source

題解:沒什麼意思的一道閱讀理解題,考慮到對於每一個節點,若要對答案有貢獻,則蟻群數量在一個區間【l,r】,l,r與當前節點的父節點的度數之積有關,然後雙指標掃兩遍就行了,注意這題要設一個inf。

#include<bits/stdc++.h>
using namespace std;
const int N=2000005;
const long long inf=1000000009;
typedef long long ll;
typedef pair<ll,int> pli;
int read(){
    int x=0,f=1; char ch=getchar();
    while (ch<'0'||ch>'9'){if (ch=='-') f=-1; ch=getchar();}
    while (ch>='0'&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    return x*f;
}
struct Edg{
    int nxt,poi;
}e[N*2];
long long a[N],ri[N],b[N],m[N];
int fir[N],l=0,n,k,r1,r2,d[N],sol[N];
void addedge(int u,int v){
    l++;
    e[l].nxt=fir[u];
    e[l].poi=v;
    fir[u]=l;
}
void dfs(int u,int f){
    for (int p=fir[u];p;p=e[p].nxt){
        int v=e[p].poi;
        if (v==f) continue;
        ri[v]=ri[u]*(d[u]-1);
        if (ri[v]>inf) ri[v]=inf;
        dfs(v,u);
    }
}
pli ep[N];
int main(){
    int n=read(),g=read(),k=read();
    for (int i=1;i<=g;i++) m[i]=read();
    for (int i=1;i<n;i++){
        int x=read(),y=read();
        d[x]++; d[y]++;
        addedge(x,y); addedge(y,x); if (i==1){r1=x; r2=y;}
    } ri[r1]=ri[r2]=1;
    dfs(r1,r2); 
    dfs(r2,r1);
    for (int i=1;i<=n;i++){
        a[i]=ri[i]*k; b[i]=(ri[i])*(k+1)-1;
        if (ri[i]==1) b[i]=a[i];
        if (a[i]>inf) a[i]=inf;
        if (b[i]>inf) b[i]=inf;
    } int tot=0;
    for (int i=1;i<=n;i++){
        if (d[i]>1) continue;
        ep[++tot]=make_pair(a[i],i);
    }
    sort(m+1,m+1+g);
    sort(ep+1,ep+1+tot);
    int l=0;
    m[g+1]=(inf+2)*k+233; 
    for (int i=1;i<=tot;i++){
        while (m[l]<ep[i].first){
            l++; 
        }
        l--; if (l<0) l=0; sol[ep[i].second]-=l;
    }
    tot=0;
    for (int i=1;i<=n;i++){
        if (d[i]>1) continue;
        ep[++tot]=make_pair(b[i],i);
    }
    sort(ep+1,ep+1+tot); l=0;
    for (int i=1;i<=tot;i++){
        while (m[l]<=ep[i].first){
            l++;
        }
        l--; if (l<0) l=0; sol[ep[i].second]+=l;
    }
    ll ans=0;
    for (int i=1;i<=n;i++){
        ans+=1ll*k*sol[i];
    }
    printf("%lld\n",ans);
    return 0;
}
View Code