赛道修建 NOIP 2018

\(nlogn^2\) 猜测的时间复杂度

要提高代码能力啊
要好好对拍

哇C题我还是太天真
理一下我的做题思路

首先我列举了一系列我应该处理的问题

1.判重
2.二分
3.选m条路

然后我猜可能跟
树形DP 倍增有关

然后我就想一条路满足的条件 可能是一条链或者转折一下

然后我想的太复杂 没有从细的地方想 就凉了.....

原来是我想的太复杂

我最后是写了一条链和直径的做法...

来看正解

容易想到的是用树形DP,同时题面要求的是“最短长度最长”,就是明显的二分答案
那么我们首先应从二分答案开始入手
尽可能多地选满足条件的边
那么应该从一颗小树开始研究
他选边的条件 就是选转折边或者是选一条链
那怎样统计答案呢
这时候我们就想到了树形DP
\(f[i]\)表示i为根的子树最多能选的条数
\(g[i]\)表示 i为根的子树最大能贡献的边的长度
贪心一下每次选最小的边配最近满足条件的边
已经大于二分val的可以直接记录到答案中
muiltiset即可 注意判重
因为选的是
这题也可以二分 把这条边删去看还能否满足条件
因为选子树的一定是最优的
code:
注意STL lower_bound的时候一定要判断是否为空
muitiset


#include<stdio.h>
#include<set> 
#include<iostream> 
#include<cstdio> 
using namespace std; 
#define maxnn 100010 
#define _maxnn 200100 
int f[maxnn]; 
int g[maxnn],res[maxnn]; 
int las[_maxnn],en[_maxnn],nex[_maxnn],tot,le[_maxnn]; 
int n,m; 

void add(int a,int b,int c) { 
    en[++tot]=b; 
    nex[tot]=las[a]; 
    las[a]=tot; 
    le[tot]=c; 
} 
void dfs(int v,int fa) { 
    f[v]=fa; 
    for(int i=las[v]; i; i=nex[i]) { 
        int u=en[i]; 
        if(u!=fa) { 
            dfs(u,v); 
        } 
    } 
} 
void prdfs(int v,int fa,int lo) { 
    multiset<int  > Q; 
    multiset<int > ::iterator it; 
    multiset<int > :: iterator pos; 
    int tmp=0; 
    for(int i=las[v]; i; i=nex[i]) { 
        tmp=0; 
        int u=en[i]; 
        if(u!=fa) { 
            prdfs(u,v,lo); 
            tmp=g[u]+le[i]; 
            if(tmp>=lo) res[v]++; 
            else 
                Q.insert(tmp); 
        } 
    } 
    int maxx=0;
    while(Q.size())
	{
		multiset<int > ::iterator pos;
		pos=Q.lower_bound(lo-*Q.begin());
		if(Q.size()==1)
		{
			maxx=max(maxx,*Q.begin());
			break;
		}
		if(pos==Q.begin())
		{
			pos++;
		}
		if(pos==Q.end())
		{
			maxx=max(maxx,*Q.begin());
			Q.erase(Q.begin());
		}
		else
		{
			res[v]++;
			Q.erase(Q.begin());
			Q.erase(pos);
		}
	 }
	 g[v]=maxx; 
} 
int isok(int t) { 
    for(int i=1; i<=n; i++) { 
        res[i]=0; 
        g[i]=0; 
    } 
    prdfs(1,1,t); 
    int cnt=0; 
    for(int i=1; i<=n; i++) { 
        cnt+=res[i]; 
    } 
    return cnt; 
} 
int main() { 
//	freopen("track3.in","r",stdin);
//	freopen("o","w",stdout);
    int x,y,z; 
    scanf("%d%d",&n,&m); 
    for(int i=1; i<n; i++) { 
        scanf("%d%d%d",&x,&y,&z); 
        add(x,y,z); 
        add(y,x,z); 
    } 
    dfs(1,1); 
    int l=0,r=600000000; 
    while(l<=r) { 
        int mid=(l+r)/2; 
        if(isok(mid)>=m) { 
            l=mid+1; 
        } else { 
            r=mid-1; 
        } 
    } 
    printf("%d",r); 
}

vector:

while(!s[x].empty()){
    if(s[x].size()==1){
        return max(Max,*s[x].begin());
    }
    it=lower_bound(s[x].begin(),s[x].end(),k-*s[x].begin());
    if(it==s[x].begin()) it++;
    if(it==s[x].end()){
        Max=max(Max,*s[x].begin());
        s[x].erase(s[x].begin());
    }
    else {
        ans++;
        s[x].erase(it);
        s[x].erase(s[x].begin());
    }
}
return Max;
posted @ 2019-09-23 21:48  ALEZ  阅读(157)  评论(0编辑  收藏  举报