dtoj#4238. 交通(traffic)

题目描述:

`A` 国一年一度的盛会——国际健美操大赛就要开始了。

`A` 国共有 $n$ 座城市,构成一棵以 $1$ 号城市为根的有根树,除了 $1$ 号城市以外,每个城市都有唯一的一个依附城市。健美操大会将在 `A` 国 $n$ 个城市中的某一个举行,定义在城市 $x$ 举行盛会的交通不便程度为将城市 $x$ 删去后最大联通块的大小。

为了提高交通运输能力,`A` 国政府可以进行一次如下操作:在删去 $x$ 号城市后,可以更改某个城市的依附城市(不能对 $1$ 号城市和依附城市为 $x$ 的城市进行该操作)。现在 `A` 国的国王想要知道对于每个城市而言,在这个城市举行盛会的交通不便程度最小可能是多少。

算法标签:线段树

思路:

最优的移动策略无疑是把某一个子树从最大的联通块移动到最小的联通块。

所以得出我们要维护分割后每个联通块的内所有节点的子树大小,还有当最大联通块是自己的父亲部分时,需要和我同链的节点子树大小以及和我不同链且不再我的子树内的节点子树大小。

对于自己子树的节点大小可以在 $dfs$ 的过程中线段树合并达成,对于与我同链的可以提前用可持久化线段树维护,对于不同链也不在子树的,可以用全集-与我同链-在我的子树内的。

接下来对于 $(sz[mx]-sz[mn])/2$ 二分寻找最接近它的数。

以下代码:

#include<bits/stdc++.h>
#define il inline
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=1e5+5,inf=1e9;
int tot,q[N],top,n;
int head[N],ne[N],to[N],cnt,rt[N],ret[N],sz[N],rt1[N];
struct node{
    int l,r,num;
}t[N*80];
il int read(){
    int x,f=1;char ch;
    _(!)ch=='-'?f=-1:f;x=ch^48;
    _()x=(x<<1)+(x<<3)+(ch^48);
    return f*x;
}
bool cmp(int t1,int t2){
    return sz[t1]<sz[t2];
}
il void ins(int x,int y){
    ne[++cnt]=head[x];
    head[x]=cnt;to[cnt]=y;
}
il void insert(int &x,int l,int r,int pos){
    if(!x)x=++tot;t[x].num++;
    if(l==r)return;int mid=(l+r)>>1;
    if(pos<=mid)insert(t[x].l,l,mid,pos);
    else insert(t[x].r,mid+1,r,pos);
}
il void Ins(int &x,int y,int l,int r,int pos){
    t[x=++tot]=t[y];t[x].num++;
    if(l==r)return;int mid=(l+r)>>1;
    if(pos<=mid)Ins(t[x].l,t[y].l,l,mid,pos);
    else Ins(t[x].r,t[y].r,mid+1,r,pos);
}
il void dfs(int x){
    sz[x]=1;
    for(int i=head[x];i;i=ne[i]){
        dfs(to[i]),sz[x]+=sz[to[i]];
    }
}
il void dfs1(int x){
    for(int i=head[x];i;i=ne[i]){
        Ins(rt1[to[i]],rt1[x],1,n,sz[x]);
        dfs1(to[i]);
    }
    insert(rt[0],1,n,sz[x]);
}
il void merge(int &x,int y,int l,int r){
    if(!x||!y){x=x+y;return;}
    t[x].num+=t[y].num;if(l==r)return;
    int mid=(l+r)>>1;
    merge(t[x].l,t[y].l,l,mid);
    merge(t[x].r,t[y].r,mid+1,r);
    
}
il bool query(int x,int l,int r,int ql,int qr){
    if(!t[x].num)return 0;
    if(ql<=l&&r<=qr)return 1;
    int mid=(l+r)>>1;
    if(ql<=mid&&query(t[x].l,l,mid,ql,qr))return 1;
    if(mid<qr&&query(t[x].r,mid+1,r,ql,qr))return 1;
    return 0;
}
il int bigger(int x,int v){
    if(!query(x,1,n,v,n))return inf;
    int l=v,r=n,res=inf;
    while(l<=r){
        int mid=(l+r)>>1;
        if(query(x,1,n,v,mid))res=mid,r=mid-1;
        else l=mid+1;
    }
    return res;
}
il int smler(int x,int v){
    if(!query(x,1,n,1,v))return inf;
    int l=1,r=v,res=inf;
    while(l<=r){
        int mid=(l+r)>>1;
        if(query(x,1,n,mid,v))l=mid+1,res=mid;
        else r=mid-1;
    }
    return res;
}
il bool Q(int x,int y,int z,int l,int r,int ql,int qr){
    if((t[z].num-t[x].num-t[y].num)==0)return 0;
    if(ql<=l&&r<=qr)return 1;
    int mid=(l+r)>>1;
    if(ql<=mid&&Q(t[x].l,t[y].l,t[z].l,l,mid,ql,qr))return 1;
    if(mid<qr&&Q(t[x].r,t[y].r,t[z].r,mid+1,r,ql,qr))return 1;
    return 0;
}
il int B(int x,int y,int z,int v){
    if(!Q(x,y,z,1,n,v,n))return inf;
    int l=v,r=n,res=inf;
    while(l<=r){
        int mid=(l+r)>>1;
        if(Q(x,y,z,1,n,v,mid))res=mid,r=mid-1;
        else l=mid+1;
    }
    return res;
}
il int S(int x,int y,int z,int v){
    if(!Q(x,y,z,1,n,1,v))return inf;
    int l=1,r=v,res=inf;
    while(l<=r){
        int mid=(l+r)>>1;
        if(Q(x,y,z,1,n,mid,v))l=mid+1,res=mid;
        else r=mid-1;
    }
    return res;
}
il void dfs2(int x){
    for(int i=head[x];i;i=ne[i])dfs2(to[i]);
    if(!head[x]){insert(rt[x],1,n,sz[x]);ret[x]=n-1;return;}
    top=0;
    for(int i=head[x];i;i=ne[i])q[++top]=to[i];
    if(x!=1)q[++top]=0,sz[0]=n-sz[x];
    sort(q+1,q+1+top,cmp);
    int res=sz[q[top]],y;
    if(top==1){ret[x]=sz[q[1]];return;}
    if(q[top]!=0){
        int st;
        st=(sz[q[top]]-sz[q[1]]+1)/2;
        y=bigger(rt[q[top]],st);
        res=min(max(sz[q[1]]+y,sz[q[top]]-y),res);
        y=smler(rt[q[top]],st);
        res=min(max(sz[q[1]]+y,sz[q[top]]-y),res);
    }
    insert(rt[x],1,n,sz[x]);
    for(int i=head[x];i;i=ne[i])merge(rt[x],rt[to[i]],1,n);
    if(q[top]==0){
        int st;
        st=(sz[q[top]]-sz[q[1]]+1)/2;
        y=B(rt[x],rt1[x],rt[0],st);
        res=min(max(sz[q[1]]+y,sz[q[top]]-y),res);
        y=S(rt[x],rt1[x],rt[0],st);
        res=min(max(sz[q[1]]+y,sz[q[top]]-y),res);
        st=(sz[q[top]]-sz[q[1]]+1)/2+sz[x];
        y=B(0,0,rt1[x],st);
        res=min(max(sz[q[1]]+y-sz[x],sz[q[top]]-y+sz[x]),res);
        y=S(0,0,rt1[x],st);
        res=min(max(sz[q[1]]+y-sz[x],sz[q[top]]-y+sz[x]),res);
    }
    if(top>2)res=max(res,sz[q[top-1]]);
    ret[x]=res;
}
int main()
{
    n=read();
    for(int i=2;i<=n;i++)ins(read(),i);
    dfs(1);
    rt[0]=++tot;dfs1(1);
    dfs2(1);
    for(int i=1;i<=n;i++)printf("%d\n",ret[i]);
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/Jessie-/p/10513935.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该代码如何使小车判断交通灯颜色,判断后又如何使小车做出相应反应?class navigation_demo: def init(self): # self.set_pose_pub = rospy.Publisher('/initialpose', PoseWithCovarianceStamped, queue_size=5) # nav 创建发布器用于发送目标位置 self.pub_goal = rospy.Publisher('/move_base_simple/goal', PoseStamped, queue_size=10) # 创建客户端,用于发送导航目标 self.move_base = actionlib.SimpleActionClient("move_base", MoveBaseAction) self.move_base.wait_for_server(rospy.Duration(60)) self.sub_socket = rospy.Subscriber('/socket', Int16, self.socket_cb) # traffic light self.sub_traffic = rospy.Subscriber('/traffic_light', Bool, self.traffic_light) # line check车道线检测信息 self.pub_line = rospy.Publisher('/detector_line',Bool,queue_size=10) # 交通灯信息 self.pub_color = rospy.Publisher('/detector_trafficlight',Bool,queue_size=10) self.pub_reached = rospy.Publisher('/reached',Bool,queue_size=10) self.sub_done = rospy.Subscriber('/done',Bool,self.done_cb) #add self.tf_listener = tf.TransformListener() # 等待map到base_link坐标系变换的建立 try: self.tf_listener.waitForTransform('map', 'base_link', rospy.Time(0), rospy.Duration(1.0)) except (tf.Exception, tf.ConnectivityException, tf.LookupException): pass print("tf point successful") #add 初始化 self.count = 0 self.judge = 0 self.start = 0 self.end = 0 self.traffic = False self.control = 0 self.step = 0 self.flage = 1 # self.done = False #add 交通灯状态 def traffic_light(self, color): self.traffic = color.data # self.traffic = True if (self.traffic == False): print ("traffic red") self.judge = 0 if (self.traffic == True): print ("traffic green") self.judge = 1 def get_pos(self,x1,y1): try: (trans, rot) = self.tf_listener.lookupTransform('map', 'base_link', rospy.Time(0)) except (tf.LookupException, tf.ConnectivityException, tf.ExtrapolationException): rospy.loginfo("tf Error") return None euler = transformations.euler_from_quaternion(rot) #print euler[2] / pi * 180 获取xy的坐标 x = trans[0] y = trans[1] # 计算当前位置与目标位置的距离 result = pow(abs(x-x1),2)+pow(abs(y-y1),2) result = sqrt(result) if (result <= 0.6):# 如果距离小于0.6,表示到达目标, return True #th = euler[2] / pi * 180 else: return False #return (x, y, th)
07-11

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值