LYDSY模拟赛day2 Dash Speed

/*
弃坑
*/
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=70010,M=N*20;
int n,m,i,g[N],v[N<<1],nxt[N<<1],ed,cur,ans[N];
int size[N],f[N],d[N],son[N],top[N];
int fa[N],dep[N],A[N],B[N];
int G[262150],V[M],W[M],NXT[M],ED;
struct E{int t,x,y;E(){}E(int _t,int _x,int _y){t=_t,x=_x,y=_y;}}q[N<<2];
void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x){
  size[x]=1;
  for(int i=g[x];i;i=nxt[i])if(v[i]!=f[x]){
    f[v[i]]=x,d[v[i]]=d[x]+1;
    dfs(v[i]),size[x]+=size[v[i]];
    if(size[v[i]]>size[son[x]])son[x]=v[i];
  }
}
void dfs2(int x,int y){
  top[x]=y;
  if(son[x])dfs2(son[x],y);
  for(int i=g[x];i;i=nxt[i])if(v[i]!=son[x]&&v[i]!=f[x])dfs2(v[i],v[i]);
}
int lca(int x,int y){
  for(;top[x]!=top[y];x=f[top[x]])if(d[top[x]]<d[top[y]])swap(x,y);
  return d[x]<d[y]?x:y;
}
int dis(int x,int y){return d[x]+d[y]-2*d[lca(x,y)];}
int F(int x){return fa[x]==x?x:F(fa[x]);}
void merge(int x,int y,int&ret){
  x=F(x),y=F(y);
  int u,v,t=-1,tmp;
  tmp=dis(A[x],B[x]);
  if(tmp>t)t=tmp,u=A[x],v=B[x];
  tmp=dis(A[x],A[y]);
  if(tmp>t)t=tmp,u=A[x],v=A[y];
  tmp=dis(A[x],B[y]);
  if(tmp>t)t=tmp,u=A[x],v=B[y];
  tmp=dis(B[x],A[y]);
  if(tmp>t)t=tmp,u=B[x],v=A[y];
  tmp=dis(B[x],B[y]);
  if(tmp>t)t=tmp,u=B[x],v=B[y];
  tmp=dis(A[y],B[y]);
  if(tmp>t)t=tmp,u=A[y],v=B[y];
  if(ret<t)ret=t;
  if(dep[x]==dep[y]){
    dep[x]++;
    q[++cur]=E(0,x,0);
  }
  if(dep[x]<dep[y])swap(x,y);
  q[++cur]=E(1,y,0);
  q[++cur]=E(2,x,A[x]);
  q[++cur]=E(3,x,B[x]);
  fa[y]=x,A[x]=u,B[x]=v;
}
void retrace(int t){
  while(cur>t){
    if(!q[cur].t)dep[q[cur].x]--;
    if(q[cur].t==1)fa[q[cur].x]=q[cur].x;
    if(q[cur].t==2)A[q[cur].x]=q[cur].y;
    if(q[cur].t==3)B[q[cur].x]=q[cur].y;
    cur--;
  }
}
void ins(int x,int a,int b,int c,int d,int p,int q){
  if(c<=a&&b<=d){
    V[++ED]=p;
    W[ED]=q;
    NXT[ED]=G[x];
    G[x]=ED;
    return;
  }
  int mid=(a+b)>>1;
  if(c<=mid)ins(x<<1,a,mid,c,d,p,q);
  if(d>mid)ins(x<<1|1,mid+1,b,c,d,p,q);
}
void solve(int x,int a,int b,int ret){
  int pos=cur;
  for(int i=G[x];i;i=NXT[i])merge(V[i],W[i],ret);
  if(a==b){
    ans[a]=ret;
    retrace(pos);
    return;
  }
  int mid=(a+b)>>1;
  solve(x<<1,a,mid,ret);
  solve(x<<1|1,mid+1,b,ret);
  retrace(pos);
}
int main(){
  freopen("speed.in","r",stdin);freopen("speed.out","w",stdout);
  scanf("%d%d",&n,&m);
  for(i=1;i<n;i++){
    int x,y,l,r;
    scanf("%d%d%d%d",&x,&y,&l,&r);
    add(x,y),add(y,x);
    ins(1,1,n,l,r,x,y);
  }
  dfs(1);dfs2(1,1);
  for(i=1;i<=n;i++)fa[i]=A[i]=B[i]=i;
  solve(1,1,n,0);
  while(m--)scanf("%d",&i),printf("%d\n",ans[i]);
  fclose(stdin);fclose(stdout);
  return 0;
}
时间: 2024-08-26 09:58:57

LYDSY模拟赛day2 Dash Speed的相关文章

LYDSY模拟赛day2 Market

/* orz claris,这个题的解法非常巧妙,首先是时间问题,其实这个问题只要离线处理一下就可以了,把物品和询问都按照时间排序,然后看一下能不能满足.然后,因为容量<=10^9,显然是不可能开一个这么大的数组,而且这么大一个容量,价值又很小,我们可以考虑用二分解决 对每个询问二分答案,需要判定用容量为 M 的背包是否可 以装下 mid 的价值. 设 fi 表示装了 i 价值所需的最小容量,gi 表示 min(fi,fi+1,fi+2,……). 那么只需要检查 gmid 是否不超过 M 即可.

LYDSY模拟赛day2 Divisors

/* 注意分解质因数,如果i是,那么n/i也是,这样就可以解决分解质因数的时间问题了 当 k ≥ 1 时,只有这些数的约数才会对答案产生贡献. 求出 m 个数的所有不超过 n 的约数,去重后统计即可. 求出 k = 1 到 m 的所有答案后,剩下的数字个数就是 k = 0 的答案. 时间复杂度 O(m2√a) */ #include<cstdio> #include<algorithm> const int N=205; int n,m,i,a[N],cnt,b[1000000],

CH Round #55 - Streaming #6 (NOIP模拟赛day2)解题报告

T1九九归一 描述 萌蛋在练习模n意义下的乘法时发现,总有一些数,在自乘若干次以后,会变成1.例如n=7,那么5×5 mod 7=4,4×5 mod 7=6,6×5 mod 7=2,2×5 mod 7=3,3×5 mod 7=1.如果继续乘下去,就会陷入循环当中.萌蛋还发现,这个循环的长度经常会是φ(n),即小于n且与n互质的正整数的个数.例如,φ(7)=6,而上述循环的长度也是6,因为5,4,6,2,3,1共有6个数.再如n=6,那么5×5 mod 6=1.这个循环的长度很短,只有2,而恰好φ

2016.10.30 NOIP模拟赛 day2 PM 整理

满分:300分 直接全部爆零,真的是很坑啊! 10.30的题目+数据:链接:http://pan.baidu.com/s/1jHXLace 密码:i784 T1: 题目中的难点就是每次折叠的点可能应经被覆盖了,我的做法是递归去推出它现在在哪个位置,不仅超时,而且答案错误. 也曾想过用数组去存下它当前的位置,但是被10^18的数据吓到了. 正解:并不是所有的坐标都有用,仅仅是那m个将要用到的点有用,所以每次折叠,就只对之后的有用的k个点进行更新,这样就行了. 时间复杂度O(m^2) 不会超时的.

LYDSY模拟赛day3 序列

NOIP不考可持久,弃坑

LYDSY模拟赛day1 Walk

/* 依旧考虑新增 2^20 个点. i 只需要向 i 去掉某一位的 1 的点连边. 这样一来图的边数就被压缩到了 20 · 2^20 + 2n + m,然后 BFS 求出 1 到每个点的最短路即可. 时间复杂度 O(20 · 2^20 + n + m) */ #include<cstdio> const int N=1300000,M=700010; int n,m,i,x,y,cnt,g0[N],g1[N],v[M],nxt[M],ed,h,t,q[N],d[N]; void add(in

NOI模拟赛Day2

深深的感受到了自己的水 -------------------------------------------------------------------------------------------------------------------------- T1: 题意:一棵树,有k个关键点,求分成连通块,每块至少一个关键点,使连通块最大最小. woc我为啥没想到二分,不懂啊,考试的时候是在梦游吗 二分后判断是否可行 就是一个简单的树上的贪心 可以先bfs一遍倒着来,max表示改点最

2016.10.30 NOIP模拟赛 day2 AM 整理

题目+数据:链接:http://pan.baidu.com/s/1gfBg4h1 密码:ho7o 总共得了:130分, 1:100分  2:30分(只会这30分的暴力) 3:0(毫无思路) 虽然不高,但是比较满意,因为把自己会的分数都拿到了. T1:100分 1 /* 2 T1明显是个数论题. 3 正确的思路:把n!质因数分解,把所有质因数的指数都取到最大的偶数,它们的乘积便是最终的结果. 4 有一种很快的方法在Eular筛中可以n!的质因数分解. 5 if(!is_prim[i]) 6 { 7

LYDSY模拟赛 escape

Description 给出数字N(1<=N<=10000),X(1<=x<=1000),Y(1<=Y<=1000),代表有N个敌人分布一个X行Y列的矩阵上矩形的行号从0到X-1,列号从0到Y-1再给出四个数字x1,y1,x2,y2,代表你要从点(x1,y1)移到(x2,y2).在移动的过程中你当然希望离敌人的距离的最小值最大化,现在请求出这个值最大可以为多少,以及在这个前提下你最少要走多少步才可以回到目标点.注意这里距离的定义为两点的曼哈顿距离,即某两个点的坐标分为(