【NOIP2012】DAY1+DAY2題解

不貼代碼的緣由是個人代碼在初中機房。忘記帶過來了。ios

DAY 1 T1隨便搞,可是字符串相關的題我常常犯蠢ide

T2 一個結論題,OAO可是須要高精度寫。優化

具體就是按左手的數除右手的數(仍是怎麼的來着)排個序spa

算過去就好了。證實的話QAQ不會,可是曾經想經過調試

T3 開車旅行 是個倍增 沒寫【不會】code

OAO我好鹹啊blog

 

DAY2 T1 用拓展歐幾里得解,我數學很差直接背板子了。抱歉不能給出詳細的講解。字符串

T2 借教室 這題我寫過好幾回線段樹,沒過。始終被TLE 正確作法是二分到哪個請求能夠知足,每次經過從新維護前綴和來check答案。有一個小的優化是若是此次能夠完成請求那麼下次就直接在上次的前綴和直接加。聽說能快一點。數學

T3 疫情控制 昨年和今年寫的時候都是痛不欲生,昨年直接搞了一週左右,今年還好,大約3h就寫完+調試完了 string

預處理每支軍隊到根節點用的時間。二分時間判斷可否完成。

說不清楚仍是放代碼吧。

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
using namespace std;
struct edge
{
    int nw;
    int to;
    int val;
};
edge line[100003];
int n=0,m=0,head[50003]={0},cnt=0;
int amy[50003]={0},deep[50003]={0};
int beiz[50003][21]={0},value[50003][21]={0};
int tim[50003]={0},from[50003]={0};
int xl[50003]={0};
bool mark[50003]={0},cho[50003]={0};
void add(int f,int t,int v);
void ready();//預處理
void to_do(int nw,int t);//對到不了首都的軍隊進行處理。
bool check(int nw);//check當前子樹是否須要守護(大霧 
bool ask(int t);//在規定的時間可否完成 
void dfs(int nw);
bool kp(int a,int b);
int main(void)
{
    freopen("blockade.in","r",stdin);
    freopen("blockade.out","w",stdout);
    scanf("%d",&n);
    int a=0,b=0,c=0,lf=1,rt=0,mid=0,ans=0x7fffffff;
    for(int i=1;i<n;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        rt+=c;
        add(a,b,c);
        add(b,a,c);
    }
    beiz[1][0]=1;
    deep[1]=0;
    dfs(1);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)scanf("%d",&amy[i]);
    ready();
    for(int i=1;i<=m;i++)xl[i]=i;
    sort(xl+1,xl+m+1,kp);
    while(lf<=rt)
    {
        mid=(lf+rt)/2;
        if(ask(mid))rt=mid-1,ans=min(ans,mid);
        else lf=mid+1;
    }
    if(ans==0x7fffffff)printf("-1");
    else    printf("%d",ans);
    return 0;
}

bool kp(int a,int b)
{
    if(tim[amy[a]]>tim[amy[b]])return 1;
    return 0;
}

void add(int f,int t,int v)
{
    line[++cnt].nw=t;
    line[cnt].to=head[f];
    line[cnt].val=v;
    head[f]=cnt;
    return;
}

void dfs(int nw)
{
    if(nw>n)return;
    int next=0;
    for(int i=head[nw];i>0;i=line[i].to)
    {
        next=line[i].nw;
        if(next==beiz[nw][0])continue;
        beiz[next][0]=nw;
        deep[next]=deep[nw]+1;
        value[next][0]=line[i].val;
        dfs(next);
    }
    return;
}

void ready()
{
    for(int i=1;i<=20;i++)
        for(int j=2;j<=n;j++)
            {beiz[j][i]=beiz[beiz[j][i-1]][i-1];value[j][i]=value[j][i-1]+value[beiz[j][i-1]][i-1];}
    int tot=0,x=0;
    for(int i=1;i<=n;i++)
    {
        x=i,tot=0;
        if(tim[x]!=0)continue;
        for(int j=20;j>=0;j--)
        {
            if(deep[x]-(1<<j)>=deep[1])
            {
                tot+=value[x][j];
                x=beiz[x][j];
                if(j==0)from[i]=x;
            }
        }
        tim[i]=tot;
    }
    return;
}

bool ask(int t)
{
    memset(mark,0,sizeof(mark));
    memset(cho,0,sizeof(cho));
    int next=0,point=m;
    for(int i=1;i<=m;i++)
    {
        if(tim[amy[xl[i]]]<=t)
        {
            point=i;
            break;
        }
        to_do(amy[xl[i]],t);
        cho[xl[i]]=true;
    }
    for(int i=head[1];i>0;i=line[i].to)
    {
        next=line[i].nw;
        if(check(next))continue;
        for(int j=point;j<=m;j++)
        {
            if(cho[xl[j]])continue;
            if(t-tim[amy[xl[j]]]>=line[i].val||from[amy[xl[j]]]==next)
            {
                mark[next]=true;
                cho[xl[j]]=true;
                break;
            }
        }
        if(!mark[next])return false;
    }
    return true;
}

void to_do(int nw,int t)
{
    int tot=0,x=nw;
    for(int i=20;i>=0;i--)
    {
        if(tot+value[x][i]<=t)
        {
            tot+=value[x][i];
            x=beiz[x][i];
        }
    }
    mark[x]=true;
    return;
}

bool check(int nw)
{
    if(mark[nw])return true;
    int next=0;
    bool as=false;
    for(int i=head[nw];i>0;i=line[i].to)
    {
        next=line[i].nw;
        if(next==beiz[nw][0])continue;
        if(!check(next))return false;
        else as=true;
    }
    return as;
}
View Code
相關文章
相關標籤/搜索