hihocoder 1381 Little Y's Tree

版权声明:辣鸡蒟蒻的blog https://blog.csdn.net/elijahqi/article/details/79967117

Time Limit:24000ms
Case Time Limit:4000ms
Memory Limit:512MB
Little Y has a tree of n nodes with each edge having a positive weight.

Little J has q queries, each time he will delete k edges in the tree.

Then the tree is splitted into k+1 connected componets.

Little J wants to know the sum of the distance of farthest pair of points in each connected components.

(0 when one component only has one node.)

Each query is independent with each other. This means each query is based on the original tree.

First line with an integer n, indicating the number of nodes.

Then following n-1 lines, the i-th line with three integers ui, vi, wi, indicating the i-th edge weighted wi connects ui and vi.

Then following one line with an integer q, indicating the number of queries.

For each query, the first line with an integer k, then following one line with k integers, indicating the id of the deleted edges.


For each query, output one line with an integer indicating the sum.

Sample Input
1 2 2
2 3 3
2 4 4
4 5 2
4 1 2 3 4
1 4
2 2 3
Sample Output

首先按照dfs序将整棵树映射到线段树上 针对线段树每个点维护一下子树的信息 维护这个点内直径的起点和终点 还有直径的长度 那么将两个节点合并起来的操作就是枚举一下四个端点分别计算大小 然后最后再算一遍和他们各自内部的值一共六种情况 取max那么可能会说 线段树所管辖的这段区间在树上不连续怎么办 那么很显然询问会询问的都是连续的区间 所以无所谓了

那么最后求答案 怎么求 因为题目给的是限制最多切k条边 因为切的边只会划分出子树 子树在dfs序上又是连续的区间 那么显然最后最多被分成了2*k+1的区间 那么我们针对这些区间分别求即可怎么求 大致来说就是首先判断一个区间 我是否被划分子树了 如果被划分子树了就递归去求 然后剩余的部分再一个循环 暴力将他们拼起来求答案 因为有总区间数的性质 保证了复杂度

#define lc (x<<1)
#define rc (x<<1|1)
#define ll long long
using namespace std;
inline char gc(){
    static char now[1<<16],*S,*T;
    if (T==S){T=(S=now)+fread(now,1,1<<16,stdin);if (T==S) return EOF;}
    return *S++;
inline int read(){
    int x=0,f=1;char ch=gc();
    while(!isdigit(ch)) {if(ch=='-') f=-1;ch=gc();}
    while(isdigit(ch)) x=x*10+ch-'0',ch=gc();
    return x*f;
const int N=1e5+20;
struct node{
    int y,next,z;
struct node1{
    int x,y;ll dis;
    node1(int _x,int _y,ll _dis){x=_x;y=_y;dis=_dis;}
int mn[N<<1][20],Log[N<<1],n,num=1,cnt,dep[N],pos[N],h[N],in[N],out[N],b[N<<1],k,a[N],dfn[N],now;
ll dis[N],ans;
inline void dfs(int x,int fa){
    for (int i=h[x];i;i=data[i].next){
        int y=data[i].y;if (y==fa) continue;dep[y]=dep[x]+1;
inline void init(){
    for (int j=1;j<=Log[num];++j)
        for (int i=1;i+(1<<j)-1<=num;++i)
inline int lca(int x,int y){
    x=pos[x];y=pos[y];if (x>y) swap(x,y);int t=Log[y-x+1];
    return dep[mn[x][t]]<dep[mn[y-(1<<t)+1][t]]?mn[x][t]:mn[y-(1<<t)+1][t];
inline ll calc(int x,int y){
    return dis[x]+dis[y]-(dis[lca(x,y)]<<1);
inline node1 merge(const node1 &ls,const node1 &rs){
    if (ls.dis==-1) return rs;if (rs.dis==-1) return ls;
    static int nx,ny,lx,ly,rx,ry;static ll tmp1,tmp2,tmp3,tmp4,mx;mx=0;
    if (ls.dis>mx) nx=lx,ny=ly,mx=ls.dis;
    if (rs.dis>mx) nx=rx,ny=ry,mx=rs.dis;
    if (tmp1>mx) nx=lx,ny=rx,mx=tmp1;if (tmp2>mx) nx=lx,ny=ry,mx=tmp2;
    if (tmp3>mx) nx=ly,ny=rx,mx=tmp3;if (tmp4>mx) nx=ly,ny=ry,mx=tmp4;
    return (node1){nx,ny,mx};
inline void build(int x,int l,int r){
    if (l==r) {tree[x].x=tree[x].y=dfn[l];tree[x].dis=0;return;}int mid=l+r>>1;
inline node1 query(int x,int l,int r,int l1,int r1){
    if(l1<=l&&r1>=r) return tree[x];int mid=l+r>>1;node1 tmp;
    if (l1<=mid) tmp=merge(tmp,query(lc,l,mid,l1,r1));
    if (r1>mid) tmp=merge(tmp,query(rc,mid+1,r,l1,r1));return tmp;
inline bool cmp(const int &a,const int &b){return in[a]<in[b];}
inline void solve(int l,int r){node1 tmp;int L=l;
    while(now<=k&&in[a[now]]>=l&&out[a[now]]<=r){int t;
        if(L<=in[a[t]]-1) tmp=merge(tmp,query(1,1,n,L,in[a[t]]-1));
    }if (L<=r) tmp=merge(tmp,query(1,1,n,L,r));ans+=tmp.dis;
inline void print(int x,int l,int r){
    if (l==r) {printf("%d %d %d %d %d\n",l,r,tree[x].x,tree[x].y,tree[x].dis);return;}
    int mid=l+r>>1;print(lc,l,mid);
    printf("%d %d %d %d %lld\n",l,r,tree[x].x,tree[x].y,tree[x].dis);
int main(){
//  freopen("hiho1381.in","r",stdin);
//  freopen("12.out","w",stdout);
    for (int i=1;i<=n<<1;++i) Log[i]=Log[i>>1]+1;
    for (int i=1;i<n;++i){static int x,y,z;
    }num=0;dfs(1,1);init();build(1,1,n);int q=read();
        for (int i=1;i<=k;++i) a[i]=b[read()];
    return 0;

Little White's Explore


Problem DescriptionnLittle White likes exploring. One day she finds a maze which has a shape of a rectangle of size n*m. The coordinate of the entrance is (1,1) and the precious deposits are place at (n,m).Except for these two positions, other grids' height change from time to time. At beginning,they all have the maximum height, and every second their height change by 1(increase or decrease). The grid cannot be stayed on if its height is smaller than min. Little White can jump upwards at most high meters and downwards low meters at a time. Every time, she can choose to go to the adjacent grids(up, down, left or right) or stay at the same grid. There is a lamp at grid (n,m) with height 10. Every time she jumps from i to j, she wishes to see the light of the lamp the moment she gets onto j. Little White has a height 10 and 100 units of power,which decrease by 1 unit for every second. It takes one second for her to jump from one grid to another, and the grids' height always change after her jump. She will always be at the center of the grids.n nnInputnFor each data set:nThe first line give five integers, n, m, min, high, low(2<=n,m<=35,min>=0,high>=0,low>=0).nThe next n lines, each has m integers, indicating the grids' initial and maximum height.The height of the grid first decreases, then begins to increase when it gets to 0, and then begins to decrease when it gets maximum...n nnOutputnPrint the minimum time required to get to the precious deposits. If she cannot get to the destination, print -1 instead.n nnSample Inputn5 5 0 1 1n18 20 20 20 20n18 20 20 20 20n18 20 18 18 18n18 20 18 20 18n18 18 18 20 7n5 5 7 5 8n23 16 3 2 28n26 8 1 16 19n16 17 26 12 4n30 1 3 3 4n14 4 7 28 12n nnSample Outputn25n-1