zoukankan      html  css  js  c++  java
  • [基本操作]点分治

    众所周知

    点分治是基本操作

    ——Destinies_Gdx

    点分治是处理树上路径问题的很好的方法,它可以把树变成一棵平衡的二叉树来使很多看起来是 $O(n^2)$ 的操作变成 $O(nlogn)$ 的

    poj1741 Tree

    给你一棵树,求长度不超过 k 的简单路径数量

    sol:

    点分治

    每次找一个重心,计算 depth

    然后用双指针法计算答案

    然后递归,减去每个儿子对父亲贡献的答案

    每次双指针会计算 x 的子树内部所有答案,但其实要减去两个点都在 x 的一个子树 u 的子树里的情况

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    void fre()
    {
        freopen("mydata.in","r",stdin);
        freopen("mydata.out","w",stdout);
    }
    const int maxn = 3e5 + 10;
    int n,k,root;
    LL ans;
    int first[maxn],to[maxn << 1],nx[maxn << 1],val[maxn << 1],cnt;
    inline void add(int u,int v,int w)
    {
        to[++cnt] = v;
        nx[cnt] = first[u];
        first[u] = cnt;
        val[cnt] = w;
    }
    inline void ins(int u,int v,int w){add(u,v,w);add(v,u,w);}
    int size[maxn],f[maxn],vis[maxn],sig;
    int dis[maxn],stk[maxn],top;
    inline void getroot(int x,int fa)
    {
        size[x] = 1;f[x] = 0;
        for(int i=first[x];i;i=nx[i])
        {
            if(to[i] == fa || vis[to[i]])continue;
            getroot(to[i],x);
            size[x] += size[to[i]];
            f[x] = max(f[x],size[to[i]]);
        }
        f[x] = max(f[x],sig - size[x]);
        if(f[x] < f[root])root = x;
    }
    inline void getdep(int x,int fa)
    {
        stk[++top] = dis[x];
        for(int i=first[x];i;i=nx[i])
        {
            if(to[i] == fa || vis[to[i]])continue;
            dis[to[i]] = dis[x] + val[i];
            getdep(to[i],x);
        }
    }
    inline LL calc(int x,int len)
    {
        dis[x] = len;
        top = 0;
        getdep(x,0);
        sort(stk + 1,stk + top + 1);
        LL res = 0;
        int l = 1,r = top;
        while(l <= r)
        {
            while(stk[r] + stk[l] > k && r > l)r--;
            res += r - l;
            l++;
        }
        return res;
    }
    inline void work(int x)
    {
        vis[x] = 1;
        ans += calc(x,0);
        for(int i=first[x];i;i=nx[i])
        {
            if(vis[to[i]])continue;
            ans -= calc(to[i],val[i]);
            root = 0,sig = size[to[i]];
            getroot(to[i],x);work(root);
        }
    }
    int main()
    {
    #ifdef Ez3real
        fre();
    #endif
        while(1)
        {
            n = read(),k = read();
            cnt = 0;ans = 0;
            memset(first,0,sizeof(first));
            memset(vis,0,sizeof(vis));
            if(n == 0 && k == 0)return 0;
            for(int i=2;i<=n;i++)
            {
                int u = read(),v = read(),w = read();
                ins(u,v,w);
            }
            sig = n,root = 0;f[0] = 2147483233;
            getroot(1,0);
            work(root);
            printf("%lld
    ",ans);
        }
    }
    View Code

    bzoj2152 聪聪可可

    给一棵树,每次随机两个点,求这两个点的简单路径上边权和膜 3 余 0 的概率

    sol:

    就是找有多少路径膜 3 余 0

    所以可以记一个数组 $cnt[0/1/2]$ 表示 x 子树里膜 3 余 $0/1/2$ 的路径数

    一个子树的贡献就是 $cnt[0] imes cnt[0] + cnt[1] imes cnt[2] imes 2$

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<cstdlib>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    void fre()
    {
        freopen("mydata.in","r",stdin);
        freopen("mydata.out","w",stdout);
    }
    const int maxn = 3e5 + 10;
    int n,k,root;
    LL ans,cc;
    int first[maxn],to[maxn << 1],nx[maxn << 1],val[maxn << 1],cnt;
    inline void add(int u,int v,int w)
    {
        to[++cnt] = v;
        nx[cnt] = first[u];
        first[u] = cnt;
        val[cnt] = w;
    }
    inline void ins(int u,int v,int w){add(u,v,w);add(v,u,w);}
    int size[maxn],f[maxn],vis[maxn],sig;
    int dis[maxn],cntu[maxn];
    inline void getroot(int x,int fa)
    {
        size[x] = 1;f[x] = 0;
        for(int i=first[x];i;i=nx[i])
        {
            if(to[i] == fa || vis[to[i]])continue;
            getroot(to[i],x);
            size[x] += size[to[i]];
            f[x] = max(f[x],size[to[i]]);
        }
        f[x] = max(f[x],sig - size[x]);
        if(f[x] < f[root])root = x;
    }
    inline void getdep(int x,int fa)
    {
        cntu[dis[x] % 3]++;
        for(int i=first[x];i;i=nx[i])
        {
            if(vis[to[i]] || to[i] == fa)continue;
            dis[to[i]] = dis[x] + val[i];
            getdep(to[i],x);
        }
    }
    inline LL calc(int x,int len)
    {
        dis[x] = len;
        cntu[0] = cntu[1] = cntu[2] = 0;
        getdep(x,0);
        return 1LL * (cntu[0] * cntu[0] + cntu[1] * cntu[2] * 2);
    }
    inline void work(int x)
    {
        vis[x] = 1;
        ans += calc(x,0);
        for(int i=first[x];i;i=nx[i])
        {
            if(vis[to[i]])continue;
            ans -= calc(to[i],val[i]);
            root = 0,sig = size[to[i]];
            getroot(to[i],x);work(root);
        }
    }
    int main()
    {
    #ifdef Ez3real
        fre();
    #endif
        n = read();cc = n * n;//,k = read();
        //cnt = 0;ans = 0;
        //memset(first,0,sizeof(first));
        //memset(vis,0,sizeof(vis));
        //if(n == 0 && k == 0)return 0;
        for(int i=2;i<=n;i++)
        {
            int u = read(),v = read(),w = read() % 3;
            ins(u,v,w);
        }
        sig = n,root = 0;f[0] = 2147483233;
        getroot(1,0);
        work(root);
        printf("%lld/%lld
    ",ans / __gcd(ans,cc),cc / __gcd(ans,cc));
    }
    View Code

    bzoj1095 捉迷藏

    给一棵树,每个点黑色或者白色,q 次操作,每次改变一个点的颜色,询问两个最远黑点的距离

    sol:

    从 Destinies_Gdx 那里学习了一波动态点分治

    大概就是先建出点分治的数据结构,然后每个点维护数据结构支持修改和查询

    对于这道题我们要维护 3 个可删除的堆分别表示

    1.子树内到该分治节点的最大距离

    2.子树内到该分治节点的分治树上父节点的最大距离

    3.每个点的最大答案

    我们把每个子树里的最长链传到 2. 里,就保证了每个子树只传上来一条链,不会出现自己走到自己的情况

    全局答案就是每个点 2. 的最大值和次大值之和,每次修改的时候暴力爬树高(树高是 $O(logn)$ 的)更新这 3 个堆即可

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 100010;
    int n,m;
    int lg[maxn + maxn];
    int root,sz,size[maxn],f[maxn],vis[maxn];
    vector<int> G[maxn];
    int ind[maxn],dfn,reh[maxn],mn[maxn][24];
    int col[maxn],dep[maxn];
    
    namespace sp_lca
    {
        int size[maxn],fa[maxn],bl[maxn];
        inline void dfs1(int x)
        {
            size[x] = 1;
            for(int i=0;i<G[x].size();i++)
            {
                int to = G[x][i];
                if(to == fa[x])continue;
                fa[to] = x;dep[to] = dep[x] + 1;
                dfs1(to);size[x] += size[to];
            }
        }
        inline void dfs2(int x,int col)
        {
            bl[x] = col;int k = 0;
            for(int i=0;i<G[x].size();i++)
            {
                int to = G[x][i];
                if(to != fa[x] && size[to] > size[k])k = to;
            }
            if(!k)return;
            dfs2(k,col);
            for(int i=0;i<G[x].size();i++)
            {
                int to = G[x][i];
                if(to != fa[x] && to != k)dfs2(to,to);
            }
        }
    }
    inline int lca(int x,int y)
    {
        while(sp_lca::bl[x] != sp_lca::bl[y])
        {
            if(dep[sp_lca::bl[x]] < dep[sp_lca::bl[y]])swap(x,y);
            x = sp_lca::fa[sp_lca::bl[x]];
        }return dep[x] < dep[y] ? x : y; 
    }
    inline int caldis(int x,int y){return dep[x] + dep[y] - 2 * dep[lca(x,y)];}
    struct Del_Heap
    {
        priority_queue<int> A,B;
        inline void push(int x){A.push(x);}
        inline void del(int x){B.push(x);}
        inline int top()
        {
            while(!B.empty() && A.top() == B.top())A.pop(),B.pop();
            if(A.size())return A.top();
            else return 0;
        }
        inline int size(){return A.size() - B.size();}
        inline int sctop()
        {
            if(size() < 2)return 0;
            int tp = top();del(tp);
            int ntp = top();push(tp);
            return ntp;
        }
    }A[maxn],B[maxn],C;
    
    inline void findroot(int x,int fa)
    {
        size[x] = 1;f[x] = 0;
        for(int i=0;i<G[x].size();i++)
        {
            int to = G[x][i];
            if(to == fa || vis[to])continue;
            findroot(to,x);
            size[x] += size[to];
            f[x] = max(f[x],size[to]);
        }
        f[x] = max(f[x],sz - size[x]);
        if(f[x] < f[root])root = x;
        //cout<<root<<endl;
    }
    
    int par[maxn];
    inline void build(int x)
    {
        vis[x] = 1;
        for(int i=0;i<G[x].size();i++)
        {
            int to = G[x][i];
            if(vis[to])continue;
            sz = size[x];root = 0;findroot(to,x);
            par[root] = x;build(root);
        }
    }
    void turn_on(int x,int rt)
    {
        if(x == rt)
        {
            if(B[x].size() == 2)C.del(B[x].top());
            B[x].del(0);
        }
        if(!par[x])return;
        int fa = par[x],ds = caldis(fa,rt);
        int tp = A[x].top();A[x].del(ds);
        if(ds == tp)
        {
            int lastans = B[fa].top() + B[fa].sctop();
            int ww = B[fa].size();B[fa].del(ds);
            if(A[x].top())B[fa].push(A[x].top());
            int nowans = B[fa].top() + B[fa].sctop();
            if(nowans < lastans)
            {
                if(ww >= 2)C.del(lastans);
                if(B[fa].size() >= 2)C.push(nowans);
            }
        }
        turn_on(fa,rt);
    }
    
    void turn_off(int x,int rt)
    {
        if(x == rt)
        {
            B[x].push(0);
            if(B[x].size() == 2)C.push(B[x].top());
        }
        if(!par[x])return;
        int fa = par[x],ds = caldis(fa,rt),szb = B[fa].size();
        int tp = A[x].top();A[x].push(ds);
        if(ds > tp)
        {
            int lastans = B[fa].top() + B[fa].sctop();
            if(tp)B[fa].del(tp);B[fa].push(ds);
            int nowans = B[fa].top() + B[fa].sctop();
            if(nowans > lastans)
            {
                if(szb >= 2)C.del(lastans);
                if(B[fa].size() >= 2)C.push(nowans);
            }
        }
        turn_off(fa,rt);
    }
    int main()
    {
        n = read();
        for(int i=2;i<=n;i++)
        {
            int u = read(),v = read();
            G[u].push_back(v);
            G[v].push_back(u);
        }
        sp_lca::dfs1(1);
        sp_lca::dfs2(1,1);
        sz = n,root = 0;f[0] = 2147483233;
        findroot(1,0);
        build(root);
        for(int i=1;i<=n;i++)A[i].push(0);
        for(int i=1;i<=n;i++){col[i] = 1;turn_off(i,i);}
        int nw = n;m = read();char opt[10];
        while(m--)
        {
            scanf("%s",opt + 1);
            if(opt[1] == 'G')
            {
                if(nw <= 1)printf("%d
    ",nw - 1);
                else printf("%d
    ",C.top());
            }
            else
            {
                int x = read();
                if(col[x] == 1)turn_on(x,x),nw--;
                else turn_off(x,x),nw++;
                col[x] ^= 1;
            }
        }
    }
    View Code

    bzoj3924 幻想乡战略游戏

    给一棵带边权的树,q 次操作,每次单点点权加,和查询树上带权重心

    sol:

    感觉动态点分治就是要记录它的信息和它传给它父亲的信息来去重。。。

    记 $A_x$ 为子树和

    $B_x$ 为子树到它的权值和

    $C_x$ 为子树到它父亲的权值和

    算一下就可以了

    注意 LCA 要 $O(1)$

    #include<bits/stdc++.h>
    #define LL long long
    const int maxn = 400010;
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    int m,n;
    int first[maxn],to[maxn],next[maxn],val[maxn],cnt;
    inline void add(int u,int v,int w)
    {
        to[++cnt]=v;
        val[cnt]=w;
        next[cnt]=first[u];
        first[u]=cnt;
    }
    int dep[maxn],dis[maxn],fat[maxn][22],s[maxn];
    int id[maxn],ip[maxn],top;
    void dfs(int u,int fa)  
    {  
        s[++top]=u;  
        if(!id[u])id[u]=top;  
        dep[top]=dep[ip[fa]]+1;ip[u]=top;  
        for(int i=first[u];i;i=next[i])  
        {  
            int v=to[i];  
            if(v==fa)continue;  
            dis[v]=dis[u]+val[i];  
            dfs(v,u);s[++top]=u;dep[top]=dep[ip[fa]+1];  
       } 
    }  
    void make()
    {
        for(int i=1;i<=top;i++) fat[i][0]=i;  
        for(int j=1;j<=18;j++)  
            for(int i=1;i<=top;i++) 
                if(i+(1<<j)-1<=top)  
                {  
                    int x=fat[i][j-1],y=fat[i+(1<<j-1)][j-1];  
                    if(dep[fat[i][j-1]]<dep[fat[i+(1<<j-1)][j-1]]) fat[i][j]=fat[i][j-1];  
                    else fat[i][j]=fat[i+(1<<j-1)][j-1];  
                }
    }
    inline int query(int l,int r)
    {
        int len=r-l+1,k=0;  
        for(k=0;1<<k+1<=len;k++);  
        if(dep[fat[l][k]]<dep[fat[r-(1<<k)+1][k]])return fat[l][k];  
        else return fat[r-(1<<k)+1][k];
    }
    inline int lca(int u,int v)
    {
        if(id[u]>id[v]) swap(u,v);  
        return s[query(id[u],id[v])];
    }
    inline int caldis(int u,int v)
    {
        int LCA=lca(u,v);
        return dis[u]+dis[v]-2*dis[LCA];
    }
    int rt,sum,f[maxn],size[maxn],vis[maxn];
    inline void GetRT(int x,int fa)
    {
        size[x]=1;f[x]=0;
        for(int i=first[x];i;i=next[i])
        {
            if(to[i]==fa || vis[to[i]])continue;
            GetRT(to[i],x);size[x]+=size[to[i]];  
            f[x]=max(f[x],size[to[i]]);  
        }
        f[x]=max(f[x],sum-size[x]);  
        if(f[x]<f[rt])rt=x;  
    }
    int ret,dv[maxn],par[maxn];
    LL ans[maxn],anss[maxn],summ[maxn];
    inline void work(int x)
    {
        vis[x]=1;summ[x]=ret;
        for(int i=first[x];i;i=next[i])
        {
            if(vis[to[i]])continue;
            rt=0,sum=size[to[i]];
            GetRT(to[i],0);
            par[rt]=x;work(rt);
        }
    }
    LL cal(int u)
    {
        LL ret=ans[u];
        for(int i=u;par[i];i=par[i])
        {
            LL delt=caldis(par[i],u);
            ret+=(ans[par[i]]-anss[i]);  
            ret+=delt*(summ[par[i]]-summ[i]); 
        }
        return ret;
    }
    LL update(int u,int va)
    {
        summ[u]+=va;  
        for(int i=u;par[i];i=par[i])  
        {  
            LL di=caldis(par[i],u);  
            summ[par[i]]+=va;  
            anss[i]+=va*di;  
            ans[par[i]]+=va*di;  
        }
    }
    int last=1;
    LL query(int u)
    {
        LL ka=cal(u);
        for(int i=first[u];i;i=next[i])
        {
            LL tmp=cal(to[i]);
            if(tmp < ka)return query(to[i]);
        }
        last=u;
        return ka;
    }
    int main()
    {
        n = read(),m = read();
        for(int i=1;i<n;i++)
        {
            int u = read(),v = read(),w = read();
            add(u,v,w),add(v,u,w);
        }top=0,dfs(1,0);
        make();sum=f[0]=n;GetRT(1,0);  
        work(rt);  
        for(int i=1;i<=m;i++)  
        {  
            int a = read(),b = read();
            update(a,b);  
            printf("%lld
    ",query(last));  
        }
    }
    View Code

    bzoj4012 开店

    给一棵有点权和边权的树,每次给一个 $u$ 和一个值域 $[L,R]$,求点权在 $[L,R]$ 的点到 $u$ 的距离和

    sol:

    对每个分治重心记一下子树内点数,子树到重心的距离和,子树到重心父亲的距离和

    对于点权,我们对每个点开一个 vector 存子树内不同颜色的前三种信息前缀和,每次查询二分,暴力爬树高,对每层重心的 vector 二分找到 $[L,R]$ 区间,然后计算 $[1,R] - [1,L-1]$ 的贡献即可

    因为很懒所以 $LCA$ 不是 $O(1)$ 的

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    inline int read()
    {
        int x = 0,f = 1;char ch = getchar();
        for(;!isdigit(ch);ch = getchar())if(ch == '-') f = -f;
        for(;isdigit(ch);ch = getchar())x = 10 * x + ch - '0';
        return x * f;
    }
    const int maxn = 200010;
    int n,q,A,yr[maxn];
    int first[maxn],to[maxn << 1],nx[maxn << 1],val[maxn << 1],cnt;
    inline void add(int u,int v,int w)
    {
        to[++cnt] = v;
        nx[cnt] = first[u];
        first[u] = cnt;
        val[cnt] = w;
    }
    LL dis[maxn];
    int fa[maxn];
    namespace LCA
    {
        int dep[maxn],bl[maxn],size[maxn];
        inline void dfs1(int x)
        {
            size[x] = 1;
            for(int i=first[x];i;i=nx[i])
            {
                if(to[i] == fa[x])continue;
                fa[to[i]] = x;dep[to[i]] = dep[x] + 1;
                dis[to[i]] = dis[x] + val[i];
                dfs1(to[i]);size[x] += size[to[i]];
            }
        }
        inline void dfs2(int x,int col)
        {
            int k = 0;
            bl[x] = col;
            for(int i=first[x];i;i=nx[i])
                if(dep[to[i]] > dep[x] && size[to[i]] > size[k])k = to[i];
            if(!k)return;
            dfs2(k,col);
            for(int i=first[x];i;i=nx[i])
                if(dep[to[i]] > dep[x] && to[i] != k)dfs2(to[i],to[i]);
        }
        inline int lca(int x,int y)
        {
            while(bl[x] != bl[y])
            {
                if(dep[bl[x]] < dep[bl[y]])swap(x,y);
                x = fa[bl[x]];
            }
            return dep[x] > dep[y] ? y : x;
        }
    }
    struct Node
    {
        LL col,sum,sig,cnt;
        inline bool operator < (const Node &b)const{return col < b.col;}
    };vector<Node> G[maxn];
    inline LL caldis(int x,int y)
    {
    //    cout<<dis[x] + dis[y] - 2 * dis[LCA::lca(x,y)]<<endl;
        if(!x || !y)return 0;
        return dis[x] + dis[y] - 2 * dis[LCA::lca(x,y)];
    }
    int f[maxn],size[maxn],vis[maxn],par[maxn],sig,root;
    void findroot(int x,int fa)
    {
        f[x] = 0,size[x] = 1;
        for(int i=first[x];i;i=nx[i])
        {
            if(to[i] == fa || vis[to[i]])continue;
            findroot(to[i],x);size[x] += size[to[i]];
            f[x] = max(f[x],size[to[i]]);
        }f[x] = max(f[x],sig - size[x]);
        if(f[x] < f[root])root = x;
    }
    void add_node(int x,int fa,int rt)
    {
        G[rt].push_back((Node){yr[x],caldis(x,rt),(par[rt] ? caldis(x,par[rt]) : 0),1});
        
        for(int i=first[x];i;i=nx[i])
        {
            if(to[i] == fa || vis[to[i]])continue;
            add_node(to[i],x,rt);
        }
    }
    void build(int x)
    {
        vis[x] = 1;add_node(x,0,x);
        G[x].push_back((Node){-1,0,0,0});
        sort(G[x].begin(),G[x].end());
        for(int i=1;i<G[x].size();i++)
        {
            G[x][i].sum += G[x][i-1].sum;
            G[x][i].sig += G[x][i-1].sig;
            G[x][i].cnt += G[x][i-1].cnt;
        }
        for(int i=first[x];i;i=nx[i])
        {
            if(vis[to[i]])continue;
            root = 0;sig = size[to[i]];
            findroot(to[i],0);par[root] = x;
            build(root);
        }
    }
    LL query(int x,int ql,int qr)
    {
        LL ans = 0;
        for(int i=x;i;i=par[i])
        {
            int st,ed;
            int l = 0,r = G[i].size() - 1;
            while(l <= r)
            {
                int mid = (l + r) >> 1;
                if(G[i][mid].col <= qr)l = mid + 1;
                else r = mid - 1;
            }
            ed = l - 1;
            l = 0,r = G[i].size() - 1;
            while(l <= r)
            {
                int mid = (l + r) >> 1;
                if(G[i][mid].col <= ql - 1)l = mid + 1;
                else r = mid - 1;
            }
            st = l - 1;
        //    cout<<st<<" "<<ed<<endl;
            ans += (G[i][ed].sum - G[i][st].sum);
            if(i != x) ans += (G[i][ed].cnt - G[i][st].cnt) * caldis(i,x);
            if(par[i]) ans -= (G[i][ed].sig - G[i][st].sig) + (G[i][ed].cnt - G[i][st].cnt) * caldis(x,par[i]);
        }return ans;
    }
    int main()
    {
        n = read(),q = read(),A = read();
        for(int i=1;i<=n;i++)yr[i] = read();
        for(int i=2;i<=n;i++)
        {
            int u = read(),v = read(),w = read();
            add(u,v,w);add(v,u,w);
        }LCA::dep[1] = 1;LCA::dfs1(1);LCA::dfs2(1,1);
        sig = n;size[0] = f[0] = 2147483233;
        findroot(1,0);build(root);
        LL lastans = 0;
        while(q--)
        {
            int x = read(),a = read(),b = read();
            int l=min((a+lastans)%A,(b+lastans)%A);
            int r=max((a+lastans)%A,(b+lastans)%A);
            printf("%lld
    ",lastans=query(x,l,r));
        }
    }
    View Code
  • 相关阅读:
    本地复现Zabbix v2.2.x, 3.0.0-3.0.3 jsrpc 参数 profileIdx2 SQL 注入漏洞
    本地搭建复现st2-045漏洞
    Ubuntu安装Vulapps漏洞靶场
    如何在腾讯云Ubuntu服务器安装kali下的神器
    nginx 跳转配置
    Chocolatey 的安装
    MySQL 5.1 主从同步配置
    针对Windows Server 2008 Web 服务 IIS+php 配置的一些心得
    解决IIS7+php的组合上传限制30M的问题
    ssh 文件权限影响登录
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/9996834.html
Copyright © 2011-2022 走看看