zoukankan      html  css  js  c++  java
  • [学习笔记]LCT进阶操作

    LCT总结——应用篇(附题单)(LCT)

    一般都是维护链的操作。split即可搞定。

    进阶操作的话,处理好辅助树和原树的关系即可搞定。

    其实,最大的区别就是,splay随便转,辅助树形态变了,但是原树形态不变,makert会让原树形态变化

    LCT维护子树信息

    真儿子会splay的时候各种变化,但是虚儿子只会在access和link的时候发生变化,其他的时候可以理解为跟着转。

    以处理子树sz为例,

    处理虚边子树sz,总sz(包括实边)两个

    pushup注意下。

    access和link注意下。

    需要真正找子树信息的时候,考虑把x的后继access掉,把xsplay到根,然后虚边子树的sz就是子树sz了。(前提,makert的根不在x子树里)

    模板题:

    [BJOI2014]大融合

    注意查询x,y的子树大小的话,makert(x),access(y),splay(y).

    其实x,y直接连通,所以现在是一个长度为2的链,y是根,x是y的右儿子,然后直接(si[y]+1)*(si[x]+1)即可。(si[x]+1可以换成s[x])

    #include<bits/stdc++.h>
    #define il inline
    #define reg register int
    #define numb (ch^'0')
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=1e5+5;
    int ch[N][2],fa[N],si[N],s[N];
    int r[N];
    int n,q;
    bool nrt(int x){
        return (ch[fa[x]][0]==x)||(ch[fa[x]][1]==x);
    }
    void pushup(int x){
        if(x) s[x]=s[ch[x][0]]+s[ch[x][1]]+si[x]+1;
    }
    void rev(int x){
        swap(ch[x][0],ch[x][1]);
        r[x]^=1;
    }
    void pushdown(int x){
        if(r[x]){
            rev(ch[x][0]);rev(ch[x][1]);
            r[x]=0;
        }
    }
    void rotate(int x){
        int y=fa[x],d=ch[fa[x]][1]==x;
        fa[ch[y][d]=ch[x][!d]]=y;
        if(nrt(y)) ch[fa[x]=fa[y]][ch[fa[y]][1]==y]=x;
        else fa[x]=fa[y];
        ch[fa[y]=x][!d]=y;
        pushup(y);
    }
    int sta[N],top;
    void splay(int x){
        int y=x;
        sta[++top]=y;
        while(nrt(y)) y=fa[y],sta[++top]=y;
        while(top) pushdown(sta[top--]);
        int z;
        while(nrt(x)){
            y=fa[x],z=fa[y];
            if(nrt(y)){
                rotate(((ch[z][0]==y)==(ch[y][0]==x))?y:x);
            }
            rotate(x);
        }
        pushup(x);
    }
    void access(int x){
        for(int y=0;x;y=x,x=fa[x]){
            splay(x);
            si[x]-=s[y];
            si[x]+=s[ch[x][1]];
            ch[x][1]=y;
            pushup(x);
        }
    }
    void makert(int x){
        access(x);
        splay(x);
        rev(x);
    }
    void link(int x,int y){
        makert(x);
        makert(y);
        si[y]+=s[x];
        s[y]+=s[x];
        fa[x]=y;
        pushup(y);
    }
    int query(int x,int y){
        makert(x);access(y);
        return (long long)(si[x]+1)*(si[y]+1);
    }
    int main(){
        rd(n);rd(q);
        char cc[2];
        int x,y;
        for(reg i=1;i<=n;++i){
            si[i]=0;s[i]=1;
        }
        while(q--){
            scanf("%s",cc+1);
            rd(x);rd(y);
            if(cc[1]=='A'){
                link(x,y);
            }else{
                printf("%d
    ",query(x,y));        
            }
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/12/18 11:13:18
    */
    大融合

    LCT维护联通块信息(边双联通分量)

    每个LCT的点,是一个边双。只不过存在一些名存实亡的点。

    只能支持插入边,维护这个边双连通分量缩点之后得到的树

    外面要再用一个并查集维护每个点所在的边双的代表节点。即并查集树的树根。

    (这里又多了一个并查集树,可以理解为,就是为了缩点打的懒标记而已(否则暴力缩点岂不是O(n)的?))

    (upda:2019.2.14:更好的解释是,其实我们扫右儿子的子树的时候,已经完成了缩点,但是右儿子的虚儿子没有记录,不能直接指向x,所以只能“懒惰”用并查集先记录一下了)

    合并缩环的时候,类似于打标记,把这个实链的点的father暴力指向x,然后干掉x的右儿子,这些部分就不存在了。

    名存实亡。都用x代替了。

    然后pushup(x)

    但是,可能这些实链的子树,还必须要继承到x上,怎么办呢?

    由于类似于打标记,先不继承它,

    因为每次处理对于链或者连通性的询问都要access,所以在这个上面做文章。

    access的时候,跳father用并查集直接跳到边双的代表点p。然后顺便把自己的辅助树的father设为p。

    这样,就会把子树继承上去了,并且真正意义上实现了缩点,

    使得边双之间用桥连接。

    由于有并查集,所以每次都要x=fin(x)找到真正的点再处理。

    看似复杂,其实理解上,就是多了一些个用并查集维护的懒标记,用到的时候及时还原即可。

    (但是对于维护边双联通分量,还要维护缩完点后的树的子树信息的话,,,,好像子树不能及时继承上去,估计就比较难办了。。2333)

    (upda:2019.2.14:上面那个说的不对,子树信息当然可以做,因为缩点对于最高点的x的子树信息没有影响的。)

    (upda:2019.3.13:emm,要看维护什么子树信息了。sz的话是不虚的,但是具体距离什么的还是没法办)

    例题1:[AHOI2005]航线规划——LCT维护边双联通分量

    例题2:【bzoj2959】长跑
    维护的sz变成sz[x]=sz[ls]+sz[rs]+my[x]
    my[x]是自己边双内部的刷卡机个数

    对于2操作,找到真正的边双点,my[root]+=new-old[x],old[x]=new;

    操作3直接查询链上的sz即可。

    #include<bits/stdc++.h>
    #define il inline
    #define reg register int
    #define numb (ch^'0')
    #define ls t[x].ch[0]
    #define rs t[x].ch[1]
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=150000+5;
    int n,m;
    struct node{
        int sz,fa,ch[2],r;
        int my;
    }t[N];
    int fa[N];
    int fin(int x){
        return fa[x]==x?x:fa[x]=fin(fa[x]);
    }
    bool nrt(int x){
        return (t[t[x].fa].ch[0]==x)||(t[t[x].fa].ch[1]==x);
    }
    void rev(int x){
        swap(t[x].ch[0],t[x].ch[1]);
        t[x].r^=1;    
    }
    void pushdown(int x){
        if(t[x].r){
            t[x].r=0;
            rev(ls);rev(rs);
        }
    }
    void pushup(int x){
        if(x) t[x].sz=t[ls].sz+t[rs].sz+t[x].my;
    }
    void rotate(int x){
        int y=t[x].fa,d=t[y].ch[1]==x;
        t[t[y].ch[d]=t[x].ch[!d]].fa=y;
        if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x;
        else t[x].fa=t[y].fa;
        t[t[y].fa=x].ch[!d]=y;
        pushup(y);
    }
    int sta[N];
    void splay(int x){
        int y=x,z=0;
        sta[++z]=y;
        while(nrt(y)) y=t[y].fa,sta[++z]=y;
        while(z) pushdown(sta[z--]);
        
        while(nrt(x)){
            y=t[x].fa,z=t[y].fa;
            if(nrt(y)){
                rotate(((t[y].ch[0]==x)==(t[z].ch[0]==y))?y:x);            
            }
            rotate(x);
        }
        pushup(x);
    }
    void access(int x){
        for(reg y=0;x;y=x,x=t[y].fa=fin(t[x].fa)){
            splay(x);rs=y;pushup(x);
        }
    }
    void makert(int x){
        access(x);splay(x);rev(x);
    }
    int findrt(int x){
        access(x);splay(x);
        pushdown(x);
        while(t[x].ch[0]) pushdown(x=t[x].ch[0]);
        splay(x);
        return x;
    }
    void dele(int x,int y){
        if(x) fa[x]=y,t[y].my+=t[x].my,dele(ls,y),dele(rs,y);
    }
    void merge(int x,int y){
        if(x==y) return;
        makert(x);
        if(findrt(y)!=x){
            t[x].fa=y;
            pushup(y);
            return;
        }
        dele(t[x].ch[1],x);
        t[x].ch[1]=0;
        pushup(x);
    }
    void split(int x,int y){
        makert(x);access(y);splay(y);
    }
    int query(int x,int y){
        makert(x);
        if(findrt(y)!=x) return -1;
        splay(y);
        return t[y].sz;
    }
    int now[N];
    int main(){
        rd(n);rd(m);
        int x,y;    
        for(reg i=1;i<=n;++i){
            rd(x);
            now[i]=x;
            fa[i]=i;t[i].sz=x;t[i].my=x;
        }
        int c;
        for(reg i=1;i<=m;++i){
            rd(c);rd(x);rd(y);
            if(c==1){
                x=fin(x);y=fin(y);
                merge(x,y);
            }else if(c==2){
                int tmp=y-now[x];
                //cout<<" tmp "<<tmp<<endl;
                now[x]=y;
                x=fin(x);
                //cout<<" xx "<<x<<endl;
                //splay(x);
                makert(x);
                t[x].my+=tmp;
                pushup(x);
            }else{
                printf("%d
    ",query(fin(x),fin(y)));
            }
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/12/19 9:57:28
    */
    长跑

     

    LCT维护边权(常用生成树)

    边,直接变成点,因为LCT不能直接维护边。

    生成树边的信息记录在点上。

     水管局长(动态最小生成树)

    严格次小生成树(也可以不用LCT)

    最小差值生成树:

    肯定要把边排序,枚举固定一个较大值,

    暴力的做法是不断把小的加进去,直到成为一个联通块。

    考虑是否能用到上一次处理的信息,

    不断加入值的时候,如果成环,那么把环上最小值替换掉即可。

    这样,通过r-1的最小差值生成树,删除并添加一条边,就可以得到r的最小差值生成树

    正确性的话,

    如果存在一个更靠后的L使得[L,R]是生成树,那么必然是可以用R之前的边把一些小的边替换掉,之前肯定已经处理这种情况了。

    代码:

    注意:

    1.pushup更新值的时候,不严格优秀就可以更新,不能只取<,否则在相等的时候会错误。

    2.处理x,y的链的时候,时刻注意谁在上面,access(y)可能y就变到了x的祖先。以及findrt(y)也可能会。

    // luogu-judger-enable-o2
    #include<bits/stdc++.h>
    #define il inline
    #define reg register int
    #define numb (ch^'0')
    #define ls t[x].ch[0]
    #define rs t[x].ch[1]
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=50000+5;
    const int M=200000+5;
    const int inf=0x3f3f3f3f;
    int n,m;
    int tot;
    int ptr;
    struct node{
        int ch[2],fa,r;
        int mi,id;
        int val;
        int from;
    }t[N+M];
    bool nrt(int x){
        return (t[t[x].fa].ch[0]==x)||(t[t[x].fa].ch[1]==x);
    }
    void rev(int x){
        swap(t[x].ch[0],t[x].ch[1]);
        t[x].r^=1;
    }
    void pushup(int x){
        if(t[x].val<=t[ls].mi&&t[x].val<=t[rs].mi){
            t[x].mi=t[x].val;
            t[x].id=x;
        }
        else if(t[ls].mi<=t[x].val&&t[ls].mi<=t[rs].mi){
            t[x].mi=t[ls].mi;
            t[x].id=t[ls].id;
        }
        else{
            t[x].mi=t[rs].mi;
            t[x].id=t[rs].id;
        }
    }
    void pushdown(int x){
        if(t[x].r){
            rev(t[x].ch[1]),rev(t[x].ch[0]);
            t[x].r=0;
        }
    }
    void rotate(int x){
        int y=t[x].fa,d=t[y].ch[1]==x;
        t[t[y].ch[d]=t[x].ch[!d]].fa=y;
        if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x;
        else t[x].fa=t[y].fa;
        t[t[x].ch[!d]=y].fa=x;
        pushup(y);
    }
    int sta[N];
    void splay(int x){
        int y=x,z=0;
        sta[++z]=y;
        while(nrt(y)) y=t[y].fa,sta[++z]=y;
        while(z) pushdown(sta[z--]);
        
        while(nrt(x)){
            y=t[x].fa,z=t[y].fa;
            if(nrt(y)){
                rotate(((t[z].ch[1]==y)==(t[y].ch[1]==x))?y:x);
            }
            rotate(x);
        }
        pushup(x);
    }
    void access(int x){
        for(reg y=0;x;y=x,x=t[x].fa){
            splay(x);
            t[x].ch[1]=y;
            pushup(x);
        }
    }
    void makert(int x){
        //cout<<" making "<<x<<" "<<t[x].fa<<endl;
        access(x);
        //cout<<" access end "<<endl;
        splay(x);
        //cout<<" splay end "<<endl;
        rev(x);
    }
    int findrt(int x){
        access(x);splay(x);
        while(t[x].ch[0]) x=t[x].ch[0];
        splay(x);
        return x;
    }
    int c=0;
    bool in[M];
    void link(int x,int y,int z,int fr){
    //    cout<<" link "<<x<<" "<<y<<" "<<z<<" "<<fr<<" "<<tot<<endl;
        t[tot].val=z;t[tot].id=tot,t[tot].mi=z;t[tot].from=fr;
    //    cout<<" t[4] "<<t[4].mi<<" "<<t[4].id<<endl;
        in[fr]=1;
        makert(x);
    //    cout<<" sdfsdfj "<<endl;
    //    cout<<findrt(y)<<endl;
    //    cout<<" over "<<endl;
        if(findrt(y)!=x){
    //        cout<<" add new "<<endl;
            t[x].fa=tot;
            t[tot].fa=y;
    //        pushup(tot);
    //        pushup(y);
            ++c;
            return;
        }
        pushup(x);
    //    cout<<t[x].mi<<" "<<t[x].val<<" "<<ls<<" "<<rs<<" "<<t[4].mi<<" "<<t[4].id<<endl;
        int lp=t[x].id;
    //    cout<<" kil "<<lp<<" "<<t[lp].from<<" "<<t[lp].val<<endl;
        in[t[lp].from]=0;
        splay(lp);
        t[t[lp].ch[0]].fa=0;
        t[t[lp].ch[1]].fa=0;
        
        makert(x);
        t[x].fa=tot;
        t[tot].fa=y;
    }
    struct edge{
        int x,y,z;
        bool friend operator <(edge a,edge b){
            return a.z<b.z;
        }
    }e[M];
    int main(){
        rd(n);rd(m);
        int x,y,z;
        for(reg i=1;i<=m;++i){
            rd(x);rd(y);rd(z);
            e[i].x=x;e[i].y=y;e[i].z=z;
        }
        sort(e+1,e+m+1);
        tot=n;
        int ans=0x3f3f3f3f;
        t[0].val=inf,t[0].mi=inf,t[0].id=-1;
        for(reg i=1;i<=n;++i){
            t[i].val=inf;t[i].mi=inf;t[i].id=-1;
        }
        for(reg i=1;i<=m;++i){
    //        cout<<" iiii "<<i<<"---------------------------"<<" "<<e[i].z<<endl;
            ++tot;
            if(e[i].x!=e[i].y) link(e[i].x,e[i].y,e[i].z,i);
            while(in[ptr]==0) ++ptr;
            if(c==n-1){
        //        cout<<" ok "<<e[i].z<<" "<<e[ptr].z<<endl;
        //        cout<<" ptr "<<ptr<<endl;
                ans=min(ans,e[i].z-e[ptr].z);
            }
        }
        printf("%d",ans);
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/12/19 8:17:20
    */
    最小差值生成树

    LCT维护树上染色联通块

     [SDOI2017]树点涂色

    到根路径的染色好似access操作,而且每种颜色都是新出现的,并且每一种颜色的地位相同。

    用LCT维护颜色块的集合,只用到access操作,再用一个线段树维护dfs序,num[x]表示x点到根节点的路径颜色数目。

    只有在虚边变成实边的时候,才会发生真正意义上的颜色改变,会对子树答案造成影响,

    具体来说,变换重儿子的时候,把原来的位置的子树的每个num加上1,新儿子的num每个减掉1

    操作2,num[a]+num[b]-2*num[lca]+1(分类讨论一下即可证明)

    操作3,区间求max

    这个题,LCT不算是用来维护动态树的工具,只是因为access和操作1非常相似,从而进行了一个“建模”,用LCT来拟合这个操作。

    #include<bits/stdc++.h>
    #define il inline
    #define reg register int
    #define numb (ch^'0')
    #define mid ((l+r)>>1)
    using namespace std;
    typedef long long ll;
    il void rd(int &x){
        char ch;bool fl=false;
        while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
        for(x=numb;isdigit(ch=getchar());x=x*10+numb);
        (fl==true)&&(x=-x);
    }
    namespace Miracle{
    const int N=1e5+5;
    const int inf=0x3f3f3f3f;
    int mx[4*N],ad[4*N];
    int n,m;
    struct edge{
        int nxt,to;
    }e[2*N];
    struct node{
        int fa,ch[2];
    }t[N];
    int hd[N],cnt;
    void add(int x,int y){
        e[++cnt].nxt=hd[x];
        e[cnt].to=y;
        hd[x]=cnt;
    }
    int dfn[N],dfn2[N],df;
    int fdfn[N],dep[N];
    int fa[N][20];
    void dfs(int x,int d){
        dfn[x]=++df;
        fdfn[df]=x;
        dep[x]=d;
        for(reg i=hd[x];i;i=e[i].nxt){
            int y=e[i].to;
            if(y==fa[x][0]) continue;
            t[y].fa=x;
            fa[y][0]=x;
            dfs(y,d+1);
        }
        dfn2[x]=df;
    }
    void pushup(int x){
        mx[x]=max(mx[x<<1],mx[x<<1|1]);
    }
    void pushdown(int x){
        if(!ad[x]) return;
        ad[x<<1]+=ad[x];
        ad[x<<1|1]+=ad[x];
        mx[x<<1]+=ad[x];
        mx[x<<1|1]+=ad[x];
        ad[x]=0;
    }
    void build(int x,int l,int r){
        if(l==r){
            mx[x]=dep[fdfn[l]];return;
        }
        build(x<<1,l,mid);build(x<<1|1,mid+1,r);
        pushup(x);
    }
    void upda(int x,int l,int r,int L,int R,int c){
        if(L<=l&&r<=R){
            ad[x]+=c;mx[x]+=c;return;
        }
        pushdown(x);
        if(L<=mid) upda(x<<1,l,mid,L,R,c);
        if(mid<R) upda(x<<1|1,mid+1,r,L,R,c);
        pushup(x);
    }
    int query(int x,int l,int r,int p){
        if(l==r){
            return mx[x];
        }
        pushdown(x);
        if(p<=mid) return query(x<<1,l,mid,p);
        return query(x<<1|1,mid+1,r,p);
    }
    int ask(int x,int l,int r,int L,int R){
        if(L<=l&&r<=R){
            return mx[x];
        }
        pushdown(x);
        int ret=0;
        if(L<=mid) ret=max(ret,ask(x<<1,l,mid,L,R));
        if(mid<R) ret=max(ret,ask(x<<1|1,mid+1,r,L,R));
        return ret;
    }
    
    bool nrt(int x){
        return t[t[x].fa].ch[0]==x||t[t[x].fa].ch[1]==x;
    }
    void rotate(int x){
        int y=t[x].fa,d=t[y].ch[1]==x;
        t[t[y].ch[d]=t[x].ch[!d]].fa=y;
        if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x;
        else t[x].fa=t[y].fa;
        t[t[x].ch[!d]=y].fa=x;
    }
    void splay(int x){
        while(nrt(x)){
            int y=t[x].fa,z=t[y].fa;
            if(nrt(y)){
                rotate(((t[z].ch[1]==y)==(t[y].ch[1]==x))?y:x);
            }
            rotate(x);
        }
    }
    int bac(int x){
        if(t[x].ch[1]==0) return 0;
        x=t[x].ch[1];
        while(t[x].ch[0]) x=t[x].ch[0];
        return x;
    }
    int pre(int x){
        while(t[x].ch[0]) x=t[x].ch[0];
        return x;
    }
    void access(int x){
        //cout<<" accessing "<<x<<endl;
        for(reg y=0;x;y=x,x=t[x].fa){
            //cout<<" x y "<<x<<" "<<y<<endl;
            splay(x);
            int lp=bac(x);
            //cout<<" bac "<<lp<<endl;
            if(lp){
                upda(1,1,n,dfn[lp],dfn2[lp],1);
            }    
            if(y){
                lp=pre(y);
            //    cout<<" pre "<<lp<<endl;
                upda(1,1,n,dfn[lp],dfn2[lp],-1);
            }
            t[x].ch[1]=y;
        }
    }
    int lca(int x,int y){
        if(dep[x]<dep[y]) swap(x,y);
        for(reg j=19;j>=0;--j){
            if(dep[fa[x][j]]>=dep[y]){
                x=fa[x][j];
            }
        }
        if(x==y) return x;
        for(reg j=19;j>=0;--j){
            if(fa[x][j]!=fa[y][j]){
                x=fa[x][j];y=fa[y][j];
            }
        }
        return fa[x][0];
    }
    int main(){
        rd(n);rd(m);
        int x,y;
        for(reg i=1;i<n;++i){
            rd(x);rd(y);
            add(x,y);add(y,x);    
        }
        dfs(1,1);
        dep[0]=-1;
        for(reg j=1;j<=19;++j){
            for(reg i=1;i<=n;++i){
                fa[i][j]=fa[fa[i][j-1]][j-1];
            }
        }
    //    for(reg i=1;i<=n;++i){
    //        cout<<i<<" "<<dfn[i]<<" "<<fdfn[i]<<" "<<dep[i]<<endl;
    //    }
        build(1,1,n);
        int c;
        while(m--){
            rd(c);
            if(c==1){
                rd(x);
                access(x);
            }
            else if(c==2){
                rd(x);rd(y);
                int anc=lca(x,y);
            //    cout<<" anc "<<anc<<endl;
                //cout<<" ---- "<<query(1,1,n,dfn[x])<<" "<<query(1,1,n,dfn[y])<<" "<<query(1,1,n,dfn[anc])<<endl;
                printf("%d
    ",query(1,1,n,dfn[x])+query(1,1,n,dfn[y])-2*query(1,1,n,dfn[anc])+1);
            }else{
                rd(x);
                printf("%d
    ",ask(1,1,n,dfn[x],dfn2[x]));
            }
        }
        return 0;
    }
    
    }
    signed main(){
        Miracle::main();
        return 0;
    }
    
    /*
       Author: *Miracle*
       Date: 2018/12/19 20:08:02
    */
    树点涂色

     重组病毒、LCT+SAM查询区间子串问题都是这个思路

  • 相关阅读:
    转载CSDN(educast):c# 对两个Datatable的结构相同进行合并
    .net升级到4.0之后,出现'System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' or one of its depen
    转载来自博客园(poleices):C#和JavaScript交互(asp.net前台和后台互调)总结
    Bat文件 执行MSSQL 脚本
    多功能jQuery对话框插件 jBox 2.3 正式版
    十一种Web网站程序性能测试工具介绍
    大型电子商务网站架构
    Nginx负载均衡
    文语通5.0破解版下载 有详细图解安装说明
    分享8个超棒的免费高质量图标搜索引擎
  • 原文地址:https://www.cnblogs.com/Miracevin/p/10140719.html
Copyright © 2011-2022 走看看