精华内容
下载资源
问答
  • 思路:这样题一看就是树套,关键是怎么套,怎么写。(话说我也不会来着。。)最easy想到方法就是区间线段树套一个权值线段。可是区间线段标记就会变得异常复杂。所以我们就反过来套,用权值线段树套...

    题目大意:有一些位置。这些位置上能够放若干个数字。

    如今有两种操作。

    1.在区间l到r上加入一个数字x

    2.求出l到r上的第k大的数字是什么


    思路:这样的题一看就是树套树,关键是怎么套,怎么写。(话说我也不会来着。。)最easy想到的方法就是区间线段树套一个权值线段树。可是区间线段树上的标记就会变得异常复杂。所以我们就反过来套,用权值线段树套区间线段树。

    这样改动操作在外线段树上就变成了单点改动。外线段树就不用维护标记了。在里面的区间线段树上维护标记就easy多了。详细实现见代码。


    CODE:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #define MAX 50010
    #define CNT (r - l + 1)
    using namespace std;
    
    int total,asks;
    
    struct ValSegTree{
    	ValSegTree *son[2];
    	int cnt,c;
    
    	ValSegTree() {
    		son[0] = son[1] = NULL;
    		cnt = c = 0;
    	}
    	void PushDown(int k) {
    		if(son[0] == NULL)	son[0] = new ValSegTree();
    		if(son[1] == NULL)	son[1] = new ValSegTree();
    		if(c) {
    			son[0]->cnt += c * (k - (k >> 1));
    			son[0]->c += c;
    			son[1]->cnt += c * (k >> 1);
    			son[1]->c += c;
    			c = 0;
    		}
    	}
    	void Modify(int l,int r,int x,int y) {
    		if(l == x && r == y) {
    			cnt += CNT;
    			c++;
    			return ;
    		}
    		PushDown(CNT);
    		int mid = (l + r) >> 1;
    		if(y <= mid)	son[0]->Modify(l,mid,x,y);
    		else if(x > mid)	son[1]->Modify(mid + 1,r,x,y);
    		else {
    			son[0]->Modify(l,mid,x,mid);
    			son[1]->Modify(mid + 1,r,mid + 1,y);
    		}
    		cnt = son[0]->cnt + son[1]->cnt;
    	}
    	int Ask(int l,int r,int x,int y) {
    		if(!cnt)	return 0;
    		if(l == x && r == y)	return cnt;
    		PushDown(CNT);
    		int mid = (l + r) >> 1;
    		if(y <= mid)	return son[0]->Ask(l,mid,x,y);
    		if(x > mid)		return son[1]->Ask(mid + 1,r,x,y);
    		int left = son[0]->Ask(l,mid,x,mid);
    		int right = son[1]->Ask(mid + 1,r,mid + 1,y);
    		return left + right;
    	}
    };
    struct IntSegTree{
    	IntSegTree *son[2];
    	ValSegTree *root;
    
    	IntSegTree() {
    		son[0] = son[1] = NULL;
    		root = new ValSegTree();
    	}
    	void Modify(int l,int r,int _l,int _r,int x) {
    		root->Modify(1,total,_l,_r);
    		if(l == r)	return ;
    		int mid = (l + r) >> 1;
    		if(son[0] == NULL)	son[0] = new IntSegTree();
    		if(son[1] == NULL)	son[1] = new IntSegTree();
    		if(x <= mid)	son[0]->Modify(l,mid,_l,_r,x);
    		else	son[1]->Modify(mid + 1,r,_l,_r,x);
    	}
    	int Ask(int l,int r,int _l,int _r,int k) {
    		if(l == r)	return l;
    		int mid = (l + r) >> 1;
    		if(son[0] == NULL)	son[0] = new IntSegTree();
    		if(son[1] == NULL)	son[1] = new IntSegTree();
    		int temp = son[1]->root->Ask(1,total,_l,_r);
    		if(k > temp)	return son[0]->Ask(l,mid,_l,_r,k - temp);
    		else	return son[1]->Ask(mid + 1,r,_l,_r,k);
    	}
    }root;
    
    int main()
    {
    	cin >> total >> asks;
    	for(int flag,x,y,z,i = 1;i <= asks; ++i) {
    		scanf("%d%d%d%d",&flag,&x,&y,&z);
    		if(flag == 1)	root.Modify(1,total,x,y,z);
    		else	printf("%d\n",root.Ask(1,total,x,y,z));
    	}
    	return 0;
    }


    展开全文
  • 亮亮解出了卷轴隐藏秘密,来到了一片沼泽地。... “怎么还有鳄鱼!没办法,看来有些空地不能直接到达了。” 亮亮虽然没有洁癖,但是沼泽地实在太臭了,所以亮亮不会循环利用木材。而且木材不能拼接在一...

    亮亮解出了卷轴隐藏的秘密,来到了一片沼泽地。这里有很多空地,而面试直通卡可能埋在任意一块空地中,好在亮亮发现了一堆木材,他可以将木材铺在两个空地之间的沼泽地上。因为亮亮不知道面试直通卡具体在哪一块空地中,所以必须要保证任意一块空地对于亮亮来说是可以抵达的。 “怎么还有鳄鱼!没办法,看来有些空地不能直接到达了。” 亮亮虽然没有洁癖,但是沼泽地实在太臭了,所以亮亮不会循环利用木材。而且木材不能拼接在一起使用,所以亮亮必须要知道在耗费木材最少的情况下,最长的那根木材至少需要多长。

    链接:https://www.nowcoder.com/questionTerminal/59aff3b7a9094432893302c9ee7794e8
    来源:牛客网

    输入描述:
    第一行包含两个整数N(1≤N≤10000),M(1≤M≤1000000)。N表示公有N块空地。
    接下来M行,每行包含三个整数P(1≤P≤N),Q(1≤Q≤N),K代表P,Q两个间没有鳄鱼,需要耗费K的木材。
    输出描述:
    一个整数,即耗费木材最少的情况下,最长的那根木材长度。
    示例1

    输入

    4 3
    1 2 1
    2 3 1
    3 4 2
    

    输出

    2

    可以参考我博客里的另一篇 并查集 的文章。【https://mp.csdn.net/postedit/79616869】

    利用并查集的方法,再多加一个Edge排序方法。便可以解决这个问题。

    【写的时候,基础不牢固,多次卡在 Arrays对象排序问题,重点理解father[ ]的生成】

    import java.util.Arrays;
    import java.util.Comparator;
    import java.util.Scanner;
    public class Main {
        
            public static void main(String[] args){
                Scanner scanner = new Scanner(System.in);
                while(scanner.hasNext()){//while只用了一次吧
                    String[] mn = scanner.nextLine().split(" ");
                    int n = Integer.parseInt(mn[0]);
                    int m = Integer.parseInt(mn[1]);
                    //接下来读取每行的信息,存储在String mn中,并且用空格分隔开
                    Edge[] edges = new Edge[m];
                    for(int i = 0;i < m;i++){
                        //提前记录下一行的值
                        String[]  str = scanner.nextLine(). split(" ");//读取的循环在这里
                        int x =  Integer.parseInt(str[0]);
                        int y =  Integer.parseInt(str[1]);
                        int k =  Integer.parseInt(str[2]);
                        edges[i] = new Edge(x,y,k);
                }
                System.out.print(max_k(edges,n,m));
                 
                }
                scanner.close();
            }
                 
         
     
            //n是点数,m是边数,edges是边的集合
            public static int max_k(Edge[] edges,int n,int m){
                int res = 0;//返回最大值
                int[] father = new  int[n+1];
                primaryset(father,n);//father初始化,暂且认为所有节点的父点都是自己
                Arrays.sort(edges,new BykComparator());
                /*Arrays.sort(edges, new Comparator<Edge>() {
                @Override
                public int compare(Edge e1, Edge e2) {
                    return e1.k - e2.k;
                }
                });*/
                for(int i = 0;i < m;i++){
                    int fx = find(father,edges[i].x);
                    int fy = find(father,edges[i].y);
                    if(fx != fy ){ //fx和fy如果没有x->y的边的话,目前不再一个连通分支中,那么加上这条边
                        if(res < edges[i].k)
                            res = edges[i].k;
                        mix(father,fx,fy);//对于有边连接的两个点,mix一下,相当于更新father的过程
                    }
                }
                return res;
            }
             
             //初始化 father[]数组
            public static void  primaryset(int[] father,int n){
                for(int i = 0;i <= n;i++)
                    father[i] = i;
            }
            public static int find(int[] father,int x){
                int r = x;//复制当前点x,找x的父点,只有father[i]==i时,才找到这个族的根节点
                while(father[r] != r){
                    r = father[r];
                }
                //路径压缩,便于后来的直接查询
                int i= x;
                while(i != r){
                    int temp = father[i];
                    father[i] = r;
                    i = temp;
                }
                return r;//在father数组中找到x的root节点bing返回root,同时执行了路径压缩
            }
            public static  void mix(int[] father,int root1,int root2){
                if(root1 < root2){
                    father[root2] = root1;//对两个族的root点,较小的一个作为较大点的father
                }else{
                    father[root1] = root2;
                }
            }
    }
    class Edge{
        public int x;
        public int y;//边的起点终点
        public int k;//存储边权
        public Edge(int x,int y,int k){
            this.x = x;
            this.y = y;
            this.k = k;
        }
    }
    class BykComparator implements Comparator{
        public final int compare(Object e1,Object e2){
            if(((Edge)e1).k > ((Edge)e2).k )
                return 1;
            else if(((Edge)e1).k == ((Edge)e2).k )
                return 0;
            else
                return -1;
             
        }
    }


    展开全文
  • 首先用权值线段O(nlogn)O(nlogn)O(nlogn)出置换。只要每次查看当前位置后面值够不够,如果不够话,减掉后面值个数,然后回到1,然后从p开始有now个还存在位置。 置换出来了之后,好像可以用倍增...

    This way

    题意:

    现在有n个人,然后有m次操作,每次操作都做长度为k的约瑟夫,然后再按照淘汰的顺序再做约瑟夫,直到x次。问你最终的序列是怎么样的。

    题解:

    这种题目我就不是很懂。首先用权值线段树O(nlogn)O(nlogn)求出置换。只要每次查看当前位置后面的值够不够,如果不够的话,减掉后面值的个数,然后回到1,然后求从p开始有now个还存在的数的位置。
    置换求出来了之后,好像可以用倍增做,但是也有可以快速求经过了x步的做法,然后置换是有两种表示形式的:
    就拿第一个样例来举例子
    第一种置换是 3 1 5 2 4,a[i]表示上一个在a[i]位置的数会变到i位置
    第二种置换:2 4 1 5 3,a[i]表示当前在i位置上的数在下一步会变到a[i]位置
    然后对于第二种置换,假设要变换x步,那么第i个位置上的数会变到a[(i+x%len)%len]上。len表示循环的长度,因为位置只在循环内变动。
    然后再将答案按照这个置换走一下即可。

    #include<bits/stdc++.h>
    using namespace std;
    const int N=1e5+5;
    int num[N*4];
    void build(int l,int r,int root){
        if(l==r){
            num[root]=1;
            return ;
        }
        int mid=l+r>>1;
        build(l,mid,root<<1);
        build(mid+1,r,root<<1|1);
        num[root]=num[root<<1]+num[root<<1|1];
    }
    void update(int l,int r,int root,int p){
        if(l==r){
            num[root]--;
            return ;
        }
        int mid=l+r>>1;
        if(mid>=p)
            update(l,mid,root<<1,p);
        else
            update(mid+1,r,root<<1|1,p);
        num[root]=num[root<<1]+num[root<<1|1];
    }
    int q_sum(int l,int r,int root,int ql,int qr){
        if(l>=ql&&r<=qr)
            return num[root];
        int mid=l+r>>1;
        int ans=0;
        if(mid>=ql)
            ans=q_sum(l,mid,root<<1,ql,qr);
        if(mid<qr)
            ans+=q_sum(mid+1,r,root<<1|1,ql,qr);
        return ans;
    }
    int q_pos(int l,int r,int root,int v){
        if(l==r)return l;
        int mid=l+r>>1;
        if(num[root<<1]>=v)
            return q_pos(l,mid,root<<1,v);
        else
            return q_pos(mid+1,r,root<<1|1,v-num[root<<1]);
    }
    int a[N],ans[N];
    int n,m;
    int k,x;
    void finds(){//找约瑟夫环
        int cnt=0;
        for(int i=1;i<=n;i++){
            int now=k;
            if(now+cnt>num[1])
                now+=cnt-num[1];
            else
                now+=cnt;
            now%=num[1];
            if(!now)now=num[1];
            int p=q_pos(1,n,1,now);
            a[i]=p;
            update(1,n,1,p);
            if(p-1)
                cnt=q_sum(1,n,1,1,p-1);
            else
                cnt=0;
        }
    }
    int tmp[N],vis[N],ttmp[N];
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)ans[i]=i;
        while(m--){
            build(1,n,1);
            memset(vis,0,sizeof(vis));
            scanf("%d%d",&k,&x);
            finds();
            for(int i=1;i<=n;i++)//求置换
                tmp[a[i]]=i;
            for(int i=1;i<=n;i++)
                a[i]=tmp[i];
            for(int i=1;i<=n;i++){
                if(vis[i]==1)continue;
                int top=0,now=i;
                vis[now]=1;
                tmp[top++]=now;
                int ne=a[now];
                while(!vis[ne]){
                    tmp[top++]=ne;
                    now=ne,vis[now]=1,ne=a[now];
                }
                int res=x%top;
                for(int j=0;j<top;j++)//快速置换
                    ttmp[tmp[j]]=tmp[(j+res)%top];
            }
            for(int i=1;i<=n;i++)a[i]=ttmp[i];
            for(int i=1;i<=n;i++)
                tmp[a[i]]=ans[i];
            for(int i=1;i<=n;i++)
                ans[i]=tmp[i];
        }
        for(int i=1;i<=n;i++)
            printf("%d%c",ans[i]," \n"[i==n]);
        return 0;
    }
    
    展开全文
  • 就是上 (u,v)的路上的第K小的权值 解题思路:  首先对于第K小的问题 我们可以用主席搞 ,没有问题,  但是对于一个形结构,我们需要将其转化为线性,然后需要剖才能做. 然后考虑链上的第k值怎么维护 ,...

    题目链接

    题目大意: 
    就是求在树上 (u,v)的路上的第K小的权值

    解题思路: 
    首先对于求第K小的问题 我们可以用主席树搞 ,没有问题, 
    但是对于一个树形结构,我们需要将其转化为线性,然后需要树剖才能做.

    然后考虑链上的第k值怎么维护 , 
    发现如果树剖计算的话 维护不了啊 
    因为(u,v)的路 可能在很多个链上,那么不能对每个求第K值,这样明显是错误的啊,

    然后我们知道主席树其实就是维护了一个前缀和

    那么我们可以对每一个节点到根节点建立前缀和,就能找任意一个节点到根节点的第K值, 
    那么根据主席树的性质,我们就能够计算(u,v)的路上的第K值了 
    只要在查询的时候稍改变一下就行了

    cnt = sum[ls[u]]+sum[ls[v]]-sum[ls[lca(u,v)]]-sum[ls[fa[lca(u,v)]]];
     

    ///                 .-~~~~~~~~~-._       _.-~~~~~~~~~-.
    ///             __.'              ~.   .~              `.__
    ///           .'//                  \./                  \\`.
    ///        .'//                     |                     \\`.
    ///       .'// .-~"""""""~~~~-._     |     _,-~~~~"""""""~-. \\`.
    ///     .'//.-"                 `-.  |  .-'                 "-.\\`.
    ///   .'//______.============-..   \ | /   ..-============.______\\`.
    /// .'______________________________\|/______________________________`.
    #pragma GCC optimize("Ofast")
    #pragma comment(linker, "/STACK:102400000,102400000")
    #pragma GCC target(sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx) 
    #include<bits/stdc++.h>
    using namespace std;
    
    #define pi acos(-1)
    #define s_1(x) scanf("%d",&x)
    #define s_2(x,y) scanf("%d%d",&x,&y)
    #define s_3(x,y,z) scanf("%d%d%d",&x,&y,&z)
    #define s_4(x,y,z,X) scanf("%d%d%d%d",&x,&y,&z,&X)
    #define S_1(x) scan_d(x)
    #define S_2(x,y) scan_d(x),scan_d(y)
    #define S_3(x,y,z) scan_d(x),scan_d(y),scan_d(z)
    #define PI acos(-1)
    #define endl '\n'
    #define srand() srand(time(0));
    #define me(x,y) memset(x,y,sizeof(x));
    #define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
    #define close() ios::sync_with_stdio(0); cin.tie(0);
    #define FOR(x,n,i) for(int i=x;i<=n;i++)
    #define FOr(x,n,i) for(int i=x;i<n;i++)
    #define fOR(n,x,i) for(int i=n;i>=x;i--)
    #define fOr(n,x,i) for(int i=n;i>x;i--)
    #define W while
    #define sgn(x) ((x) < 0 ? -1 : (x) > 0)
    #define bug printf("***********\n");
    #define db double
    #define ll long long
    #define mp make_pair
    #define pb push_back
    #define sz size
    #define fi first
    #define se second
    #define pf printf
    typedef long long LL;
    typedef pair <int, int> ii;
    const int INF=0x3f3f3f3f;
    const LL LINF=0x3f3f3f3f3f3f3f3fLL;
    const int dx[]={-1,0,1,0,1,-1,-1,1};
    const int dy[]={0,1,0,-1,-1,1,-1,1};
    const int maxn=1e2+7;
    const int _=1e5+10;
    const double EPS=1e-8;
    const double eps=1e-8;
    const LL mod=1e9+7;
    template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
    template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
    template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
    template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
    template <class T>
    inline bool scan_d(T &ret){char c;int sgn;if (c = getchar(), c == EOF){return 0;}
    while (c != '-' && (c < '0' || c > '9')){c = getchar();}sgn = (c == '-') ? -1 : 1;ret = (c == '-') ? 0 : (c - '0');
    while (c = getchar(), c >= '0' && c <= '9'){ret = ret * 10 + (c - '0');}ret *= sgn;return 1;}
    
    inline bool scan_lf(double &num){char in;double Dec=0.1;bool IsN=false,IsD=false;in=getchar();if(in==EOF) return false;
    while(in!='-'&&in!='.'&&(in<'0'||in>'9'))in=getchar();if(in=='-'){IsN=true;num=0;}else if(in=='.'){IsD=true;num=0;}
    else num=in-'0';if(!IsD){while(in=getchar(),in>='0'&&in<='9'){num*=10;num+=in-'0';}}
    if(in!='.'){if(IsN) num=-num;return true;}else{while(in=getchar(),in>='0'&&in<='9'){num+=Dec*(in-'0');Dec*=0.1;}}
    if(IsN) num=-num;return true;}
    
    void Out(LL a){if(a < 0) { putchar('-'); a = -a; }if(a >= 10) Out(a / 10);putchar(a % 10 + '0');}
    void print(LL a){ Out(a),puts("");}
    //cerr << "run time is " << clock() << endl;
    
    int n,m;
    int w[_],b[_];
    
    struct node{
        int to,next;
    }G[_<<1];
    int head[_],tot;
    int rt[_],ls[_*20],rs[_*20],sum[_*20],chairtree,siz;
    
    void build(int &rt,int l,int r){
        rt=++chairtree;
        sum[rt]=0;
        if(l>=r)return ;
        int m =((r-l)>>1)+l;
        build(ls[rt],l,m);
        build(rs[rt],m+1,r);
    }
    
    void update(int& rt,int l,int r,int last,int pos){
        rt=++chairtree;
        ls[rt]=ls[last];
        rs[rt]=rs[last];
        sum[rt]=sum[last]+1;
    
        if(l>=r) return ;
        int m=((r-l)>>1)+l;
        if(pos<=m) update(ls[rt],l  ,m,ls[last],pos);
        else       update(rs[rt],m+1,r,rs[last],pos);
    }
    
    int query(int rt,int l,int r,int last,int lca,int flca,int k){
        if(l>=r) return l;
        int m=((r-l)>>1)+l;
        int cnt=sum[ls[rt]]+sum[ls[last]]-sum[ls[lca]]-sum[ls[flca]];
        if(k<=cnt) query(ls[rt],l  ,m,ls[last],ls[lca],ls[flca],k);
        else       query(rs[rt],m+1,r,rs[last],rs[lca],rs[flca],k-cnt);
    }
    
    void dfs(int rt,int l,int r){
    
        int m = ((r-l)>>1)+l;
        printf("%d",sum[rt]);
        if(l>=r) return ;printf("( ");
        dfs(ls[rt],l,m);printf("_%*d,",2,ls[rt]);
        dfs(rs[rt],m+1,r);printf("_%*d )",2,rs[rt]);
    }
    /**
    ChairTree end
    */
    
    void add(int u,int v){
        G[++tot].to=v,G[tot].next=head[u],head[u]=tot;
        G[++tot].to=u,G[tot].next=head[v],head[v]=tot;
    }
    
    int dep[_],fa[_],sz[_],son[_];
    void dfs1(int u,int f,int d){
        dep[u]=d,fa[u]=f,sz[u]=1,son[u]=0;
        for(int i=head[u],to;i;i=G[i].next){
            to=G[i].to;
            if(to==f)continue;
            dfs1(to,u,d+1);
            sz[u]+=sz[to];
            if(sz[son[u]]<sz[to])son[u]=to;
        }
    }
    
    int tree[_],top[_],pre[_],cnt;
    void dfs2(int u,int tp){
        top[u]=tp,tree[u]=++cnt,pre[tree[u]]=u;
        update(rt[u],1,siz,rt[fa[u]],w[u]);
        if(!son[u])return;
        dfs2(son[u],tp);
        for(int i=head[u],to;i;i=G[i].next){
            to=G[i].to;
            if(to==fa[u]||to==son[u])continue;
            dfs2(to,to);
        }
    }
    
    int Lca(int x,int y){
        int fx=top[x],fy=top[y];
        while(fx!=fy){
            if(dep[fx]<dep[fy])swap(x,y),swap(fx,fy);
            x=fa[fx],fx=top[x];
        }
        if(dep[x]>dep[y])swap(x,y);
        return x;
    }
    
     
    void solve() {
    	s_2(n,m);
    	FOR(1,n,i) s_1(w[i]),b[i]=w[i];
    	FOr(1,n,i) {
    		int u,v;
    		s_2(u,v);
    		add(u,v);
    	}
    	fa[1]=0;
    	sort(b+1,b+n+1);
    	siz=unique(b+1,b+n+1)-(b+1);
    	FOR(1,n,i)
    		w[i]=lower_bound(b+1,b+siz+1,w[i])-b;
    	build(rt[0],1,siz);
    	dfs1(1,0,1);
    	dfs2(1,1);
    	while(m--) {
    		int u,v,k;
    		s_3(u,v,k);
    		int lca=Lca(u,v);
    		//cout<<lca<<endl; 
    		print(b[query(rt[u],1,siz,rt[v],rt[lca]
    			,rt[fa[lca]],k)]);
    	}
    }
    int main() {
    	//freopen( "1.in" , "r" , stdin );
        //freopen( "1.out" , "w" , stdout );
        int t=1;
        //init();
        //s_1(t);
        for(int cas=1;cas<=t;cas++) {
            //printf("Case #%d: ",cas);
            solve();
        }
    }

     

    展开全文
  • 题目描述 志向远大YY小朋友在学完快速排序之后决定学习平衡,左思右想再加上SY教唆,YY决定学习Treap。...这时候不怎么友爱510跑了出来,他问了YY小朋友一个极不和谐问题:怎么求Treap中两个点之间...
  • 利用权值线段来动态加点,每次询问找区间内 [id+1,n] 所有数个数,由于取值线段本身具有顺序,所以可以将区间查询变为单点查询 最后注意输出一定要 printf("%lld\n") ( 用 I64 错都不知道怎么) ...
  • 权值线段:顾名思义就是每个节点用来表示一个区间数出现次数。 权值线段可以用来区间第K大等 题解: 显然两个优先队列每次去删最大瞎搞会超时O(n^2); 这时候得考虑怎么扫一遍,线性就可以得出结果...
  • 反正先一遍sa 然后这个问题可以稍微转化一下 默认比较A、B数组中元素大小都是比较它们rank大小,毕竟两个位置LCP就是它们rankrmq 然后每次只要求B[j]>...=A[i]的怎么算 排序以后从后往前推着做...
  • 现在有mmm个询问,每次问能否混合出总体积大于某个值,总价格小于某个值果汁,如果能,所有方案中用于混合果汁美味度最小值最大值。 思路: 首先考虑单次询问怎么做,看这个询问类型应该可以二分答案...
  • 现在有mmm个询问,每次问能否混合出总体积大于某个值,总价格小于某个值果汁,如果能,所有方案中用于混合果汁美味度最小值最大值。 思路: 首先考虑单次询问怎么做,看这个询问类型应该可以二分答案...
  • 【题意】 给定一棵,两个结点之间的距离为上路径的长度,要求构造一棵上所有边的权值和...那么上最长路径怎么求呢? 可以看出,离第i个结点最远的距离,是边(v,i)的长度(其中v是i 的父亲)加上第v个...
  • 如题,C++构造哈夫曼,运行时只能输入一个节点初值,然后就是 process exited with return value 3221225477,怎么回事,指点。 代码如下: #include #define Maxval 10000 using namespace std; typedef char...
  • 普利姆算法(prim)最小生成(MST)过程详解

    千次阅读 多人点赞 2018-08-14 11:13:36
    转:普利姆算法(prim)最小生成树(MST)过程详解 ...最小造价的过程也就转化成最小生成树的过程,则最小生成树表示使其造价最小的生成树。  那么怎么样用普利姆算法(prim算法)最小生成树(MST)? ...
  • 树的重心

    2020-05-11 17:02:24
    树的重心的定义: 树若以某点为根,使得该树最大子树的结点数最小,那么这个点则为该树的...怎么求树的重心: 定义几个数组:f[u]表示以u为根的总距离,size[u]表示以u为根的子树的大小(结点数,此题每个点要乘以权值
  • 浅谈次小生成

    2018-09-15 11:14:32
    今天跟大家聊聊怎么求次小生成树。 首先需要注意的是我们所说的次小生成树是指严格次小生成树。也就是我们要求的是权值大于最小生成树的权值最小的生成树。...
  • 第k大数有太多方法来了,这是一个十分基础问题,可以由很多种数据结构来完成。常用有排序、主席……。今天我要介绍一种更快更简洁算法...权值线段就是记录同数值个数线段。例如有3,5...
  • 如果给你一棵点u到点v路径上点的权值之和,你可能会说:倍增啊! 那如果出题人:我还要你支持修改某个点的权值! 或者再j一点:我还要你支持修改点u到点v路径上点的权值! 那就得用链剖分了。 2. 什么是...
  • 算法提高 树的直径

    2021-04-13 10:02:09
    题目链接 问题描述:树的直径 输入格式:输入的第一行包含一个整数n,表示树中的点数。接下来n-1行,每行3个正整数,表示连同的两点及边...那究竟要怎么实施呢,其实求树的直径有一个很简单的方法(我也是从csdn各位
  • 题解:无法使用prim求次小生成,因为可能有两个点有两个及以上权值,那么我们用prim会把大的权值覆盖掉,所以我们用kruskal求,怎么求呢?我们求出最小生成树后,把用过的边绕过,求最小生成,如果存在则存在。...
  • 浅谈链剖分

    2019-10-06 22:19:43
    传送门 捡起了之前剖的坑,之前只...u到v的路径上的所有点的权值和 修改u到v的路径上的所有点的权值 以u为根的子树的结点的权值和 修改以u为根的子树的结点的权值 LCA 怎么实现? 利用dfs序,将上节...
  • 题目给一棵,边带有权值每一点到其他点路径上最大权和。 上任意两点路径都可以看成是经过某棵子树根路径,即路径权=两个点到根路径权和,于是果断分治。 对于每次分治子树,计算其所有结点到...
  • 在一棵树里,每一条边都有权值(树里面两个点之间的边权),那么树上最远的距离就为树的直径,当然我们大多数做的都是边权为1的树,这个时候也就是树上距离最远的两个点 解树的直径的两种方法 1.树形DP ans 来记录...
  • poj2104_静态主席

    2016-10-24 21:40:32
    高中要慢慢补回来呢QAQ概念主席维护是一个前缀,相当于我们打n棵权值线段,第i棵表示在1-i范围内数在离散化之后每一个数区间出现了多少次标准姿势那么我们怎么样才可以在区间[i,j]中k小值呢?...
  • 给定一棵有nn个点的,每个点有权值viv_i,是否存在一条路径使得路径上所有点的权值的乘积mod106+3\bmod 10^6+3为kk,输出路径首尾编号,若有多解输出字典序最小的解。 貌似很像不虚就是要AK? 现在路径上点...
  • 求树上路径权值的最大异或和。 解题 以零号结点为根进行一遍dfs处理出结点u到根节点路径异或和。然后将这些异或和插入到01字典中。最后遍历这些异或和查询与其异或最大路径异或和。 昨天写这题,怎么怎么...

空空如也

空空如也

1 2 3 4 5 ... 12
收藏数 240
精华内容 96
关键字:

树的权值怎么求