树套树乱讲的代码

树套树乱讲的代码

由于部分代码的完成时间较早所以码风可能有些差异,敬请谅解。

动态区间Kth

题面
整体二分题解

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=10005;
struct segment_tree{int v;int ls,rs;}t[N*200];
struct operation{bool b;int l,r,k;int pos,t;}q[N];
int n,m,a[N],o[N<<1],rt[N],len,tot,temp[2][20],cnt[2];
char opt;
void Modify(int &now,int l,int r,int pos,int val)
{
    if (!now) now=++tot;
    t[now].v+=val;
    if (l==r) return;
    int mid=l+r>>1;
    if (pos<=mid) Modify(t[now].ls,l,mid,pos,val);
    else Modify(t[now].rs,mid+1,r,pos,val);
}
void PreModify(int x,int val)
{
    int k=lower_bound(o+1,o+len+1,a[x])-o;
    for (int i=x;i<=n;i+=i&-i) Modify(rt[i],1,len,k,val);
}
int Query(int l,int r,int k)
{
    if (l==r) return l;
    int mid=l+r>>1,sum=0;
    for (int i=1;i<=cnt[1];i++) sum+=t[t[temp[1][i]].ls].v;
    for (int i=1;i<=cnt[0];i++) sum-=t[t[temp[0][i]].ls].v;
    if (k<=sum)
    {
        for (int i=1;i<=cnt[1];i++) temp[1][i]=t[temp[1][i]].ls;
        for (int i=1;i<=cnt[0];i++) temp[0][i]=t[temp[0][i]].ls;
        return Query(l,mid,k);
    }
    else
    {
        for (int i=1;i<=cnt[1];i++) temp[1][i]=t[temp[1][i]].rs;
        for (int i=1;i<=cnt[0];i++) temp[0][i]=t[temp[0][i]].rs;
        return Query(mid+1,r,k-sum);
    }
}
int PreQuery(int l,int r,int k)
{
    memset(temp,0,sizeof(temp));
    cnt[0]=cnt[1]=0;
    for (int i=r;i;i-=i&-i) temp[1][++cnt[1]]=rt[i];
    for (int i=l-1;i;i-=i&-i) temp[0][++cnt[0]]=rt[i];
    return Query(1,len,k);
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>m;
    for (int i=1;i<=n;i++) cin>>a[i],o[++len]=a[i];
    for (int i=1;i<=m;i++)
    {
        cin>>opt;
        q[i].b=(opt=='Q');
        if (q[i].b) cin>>q[i].l>>q[i].r>>q[i].k;
        else cin>>q[i].pos>>q[i].t,o[++len]=q[i].t;
    }
    sort(o+1,o+len+1);
    len=unique(o+1,o+len+1)-o-1;
    for (int i=1;i<=n;i++) PreModify(i,1);
    for (int i=1;i<=m;i++)
    {
        if (q[i].b)
            printf("%d\n",o[PreQuery(q[i].l,q[i].r,q[i].k)]);
        else
        {
            PreModify(q[i].pos,-1);
            a[q[i].pos]=q[i].t;
            PreModify(q[i].pos,1);
        }
    }
    return 0;
}

三维偏序(陌上花开)

题面

#include<cstdio>
#include<algorithm>
using namespace std;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
const int N = 200005;
struct node{
    int a,b,c,cnt,ans;
    bool operator < (const node &zsy) const
        {
            if (a!=zsy.a) return a<zsy.a;
            if (b!=zsy.b) return b<zsy.b;
            return c<zsy.c;
        }
    bool operator == (const node &zsy) const
        {return a==zsy.a&&b==zsy.b&&c==zsy.c;}
}p[N],q[N];
struct segment_tree{int ls,rs,sum;}t[N*200];
int n,k,m,rt[N],cnt,tot[N];
void modify(int &x,int l,int r,int p,int v)
{
    if (!x) x=++cnt;t[x].sum+=v;
    if (l==r) return; int mid=l+r>>1;
    if (p<=mid) modify(t[x].ls,l,mid,p,v);
    else modify(t[x].rs,mid+1,r,p,v);
}
int query(int x,int l,int r,int ql,int qr)
{
    if (!x||(l>=ql&&r<=qr)) return t[x].sum;
    int mid=l+r>>1,s=0;
    if (ql<=mid) s+=query(t[x].ls,l,mid,ql,qr);
    if (qr>mid) s+=query(t[x].rs,mid+1,r,ql,qr);
    return s;
}
int main()
{
    n=gi();k=gi();
    for (int i=1;i<=n;++i)
        p[i]=(node){gi(),gi(),gi()};
    sort(p+1,p+n+1);
    for (int i=1;i<=n;++i)
        if (p[i]==q[m]) ++q[m].cnt;
        else q[++m]=p[i],q[m].cnt=1;
    for (int i=1;i<=m;++i)
    {
        for (int j=q[i].b;j;j-=j&-j)
            q[i].ans+=query(rt[j],1,k,1,q[i].c);
        tot[q[i].ans+q[i].cnt-1]+=q[i].cnt;
        for (int j=q[i].b;j<=k;j+=j&-j)
            modify(rt[j],1,k,q[i].c,q[i].cnt);
    }
    for (int i=0;i<n;++i)
        printf("%d\n",tot[i]);
    return 0;
}

二逼树套树

题面

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 50005;
struct tree{int ls,rs,num;}t[N*200];
struct query{int opt,l,r,pos,k;}q[N];
int n,m,a[N],o[N<<1],len,rt[N],tot,temp[2][20],cnt[2];
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
void Modify(int &x,int l,int r,int pos,int v)
{
    if (!x) x=++tot;
    t[x].num+=v;
    if (l==r) return;
    int mid=l+r>>1;
    if (pos<=mid) Modify(t[x].ls,l,mid,pos,v);else Modify(t[x].rs,mid+1,r,pos,v);
}
int Query(int x,int l,int r,int ql,int qr)
{
    if (l>=ql&&r<=qr) return t[x].num;
    int mid=l+r>>1,s=0;
    if (ql<=mid) s+=Query(t[x].ls,l,mid,ql,qr);
    if (qr>mid) s+=Query(t[x].rs,mid+1,r,ql,qr);
    return s;
}
int Find(int l,int r,int k)
{
    if (l==r) return l;
    int mid=l+r>>1,sum=0;
    for (int i=1;i<=cnt[1];i++) sum+=t[t[temp[1][i]].ls].num;
    for (int i=1;i<=cnt[0];i++) sum-=t[t[temp[0][i]].ls].num;
    if (k<=sum)
    {
        for (int i=1;i<=cnt[1];i++) temp[1][i]=t[temp[1][i]].ls;
        for (int i=1;i<=cnt[0];i++) temp[0][i]=t[temp[0][i]].ls;
        return Find(l,mid,k);
    }
    else
    {
        for (int i=1;i<=cnt[1];i++) temp[1][i]=t[temp[1][i]].rs;
        for (int i=1;i<=cnt[0];i++) temp[0][i]=t[temp[0][i]].rs;
        return Find(mid+1,r,k-sum);
    }
}
void Update(int pos,int v)
{
    for (int i=pos;i<=n;i+=i&-i)
        Modify(rt[i],1,len,a[pos],v);
}
int Sum(int l,int r,int ql,int qr)
{
    if (ql>qr) return 0;
    int sum=0;
    for (int j=r;j;j-=j&-j) sum+=Query(rt[j],1,len,ql,qr);
    for (int j=l-1;j;j-=j&-j) sum-=Query(rt[j],1,len,ql,qr);
    return sum;
}
int Rank(int l,int r,int k)
{
    cnt[1]=cnt[0]=0;
    for (int j=r;j;j-=j&-j) temp[1][++cnt[1]]=rt[j];
    for (int j=l-1;j;j-=j&-j) temp[0][++cnt[0]]=rt[j];
    return o[Find(1,len,k)];
}
int main()
{
    n=gi();m=gi();
    for (int i=1;i<=n;i++) o[++len]=a[i]=gi();
    for (int i=1;i<=m;i++)
    {
        q[i].opt=gi();
        if (q[i].opt!=3) q[i].l=gi(),q[i].r=gi();
        else q[i].pos=gi();
        q[i].k=gi();
        if (q[i].opt!=2) o[++len]=q[i].k;
    }
    sort(o+1,o+len+1);
    len=unique(o+1,o+len+1)-o-1;
    for (int i=1;i<=n;i++)
    {
        a[i]=lower_bound(o+1,o+len+1,a[i])-o;
        Update(i,1);
    }
    for (int i=1;i<=m;i++)
    {
        if (q[i].opt!=2) q[i].k=lower_bound(o+1,o+len+1,q[i].k)-o;
        if (q[i].opt==1)
            printf("%d\n",Sum(q[i].l,q[i].r,1,q[i].k-1)+1);
        if (q[i].opt==2)
            printf("%d\n",Rank(q[i].l,q[i].r,q[i].k));
        if (q[i].opt==3)
        {
            Update(q[i].pos,-1);
            a[q[i].pos]=q[i].k;
            Update(q[i].pos,1);
        }
        if (q[i].opt==4)
        {
            int sum=Sum(q[i].l,q[i].r,1,q[i].k-1);
            if (!sum) printf("-2147483647\n");
            else printf("%d\n",Rank(q[i].l,q[i].r,sum));
        }
        if (q[i].opt==5)
        {
            int sum=Sum(q[i].l,q[i].r,1,q[i].k);
            if (sum==q[i].r-q[i].l+1) printf("2147483647\n");
            else printf("%d\n",Rank(q[i].l,q[i].r,sum+1));
        }

    }
    return 0;
}

[ZJOI2013]K大数查询

题面
整体二分题解

#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 50005;
#define ll long long
struct segment_tree{
    int ls,rs,tim;ll num;
}t[N*300];
int n,m,rt[N*16],tot;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
void Modify(int &x,int l,int r,int ql,int qr)
{
    if (!x) x=++tot;
    if (l==ql&&r==qr) {t[x].tim++;return;}
    t[x].num+=qr-ql+1;
    int mid=l+r>>1;
    if (qr<=mid) Modify(t[x].ls,l,mid,ql,qr);
    else if (ql>mid) Modify(t[x].rs,mid+1,r,ql,qr);
    else Modify(t[x].ls,l,mid,ql,mid),Modify(t[x].rs,mid+1,r,mid+1,qr);
}
ll Query(int x,int l,int r,int ql,int qr)
{
    ll res=1ll*t[x].tim*(qr-ql+1);
    if (l==ql&&r==qr) return res+t[x].num;
    int mid=l+r>>1;
    if (qr<=mid) return res+Query(t[x].ls,l,mid,ql,qr);
    else if (ql>mid) return res+Query(t[x].rs,mid+1,r,ql,qr);
    else return res+Query(t[x].ls,l,mid,ql,mid)+Query(t[x].rs,mid+1,r,mid+1,qr);
}
int main()
{
    n=gi();m=gi();
    while (m--)
    {
        int opt=gi(),a=gi(),b=gi(),c=gi(),now=1,l=1,r=n;
        if (opt==1)
            while (233)
            {
                Modify(rt[now],1,n,a,b);
                if (l==r) break;
                int mid=l+r>>1;
                if (c<=mid) now=now<<1,r=mid;
                else now=now<<1|1,l=mid+1;
            }
        else
            while (l<r)
            {
                ll sum=Query(rt[now<<1|1],1,n,a,b);
                int mid=l+r>>1;
                if ((ll)c<=sum)
                    now=now<<1|1,l=mid+1;
                else c-=sum,now=now<<1,r=mid;
            }
        if (opt==2) printf("%d\n",l);
    }
    return 0;
}

[CTSC2008]网络管理

题面
整体二分题解
这份代码应该是我现在的码风

#include<cstdio>
#include<algorithm>
using namespace std;
int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=0,ch=getchar();
    while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    return w?x:-x;
}
const int N = 8e4+5;
struct segment_tree{int ls,rs,v;}t[N*200];
struct operation{int k,a,b;}q[N];
int n,m,val[N],to[N<<1],nxt[N<<1],head[N],cnt,o[N<<1],len;
int fa[N],dep[N],sz[N],son[N],top[N],dfn[N];
int rt[N],tot,tmp1[N],tmp2[N],t1,t2;
void link(int u,int v){to[++cnt]=v;nxt[cnt]=head[u];head[u]=cnt;}
void dfs1(int u,int f)
{
    fa[u]=f;dep[u]=dep[f]+1;sz[u]=1;
    for (int e=head[u];e;e=nxt[e])
    {
        int v=to[e];if (v==f) continue;
        dfs1(v,u);
        sz[u]+=sz[v];if (sz[v]>sz[son[u]]) son[u]=v;
    }
}
void dfs2(int u,int up)
{
    top[u]=up;dfn[u]=++cnt;
    if (son[u]) dfs2(son[u],up);
    for (int e=head[u];e;e=nxt[e])
        if (to[e]!=fa[u]&&to[e]!=son[u])
            dfs2(to[e],to[e]);
}
int getlca(int u,int v)
{
    while (top[u]!=top[v])
    {
        if (dep[top[u]]<dep[top[v]]) swap(u,v);
        u=fa[top[u]];
    }
    return dep[u]<dep[v]?u:v;
}
void Modify(int &x,int l,int r,int p,int v)
{
    if (!x) x=++tot;t[x].v+=v;
    if (l==r) return;int mid=l+r>>1;
    if (p<=mid) Modify(t[x].ls,l,mid,p,v);
    else Modify(t[x].rs,mid+1,r,p,v);
}
int Query(int l,int r,int k)
{
    if (l==r) return l;
    int mid=l+r>>1,sum=0;
    for (int i=1;i<=t1;++i) sum+=t[t[tmp1[i]].rs].v;
    for (int i=1;i<=t2;++i) sum-=t[t[tmp2[i]].rs].v;
    if (k<=sum)
    {
        for (int i=1;i<=t1;++i) tmp1[i]=t[tmp1[i]].rs;
        for (int i=1;i<=t2;++i) tmp2[i]=t[tmp2[i]].rs;
        return Query(mid+1,r,k);
    }
    else
    {
        for (int i=1;i<=t1;++i) tmp1[i]=t[tmp1[i]].ls;
        for (int i=1;i<=t2;++i) tmp2[i]=t[tmp2[i]].ls;
        return Query(l,mid,k-sum);
    }
}
void PreModify(int k,int p,int v)
{
    for (int i=k;i<=n;i+=i&-i)
        Modify(rt[i],1,len,p,v);
}
int PreQuery(int u,int v,int k)
{
    t1=t2=0;
    for (int i=dfn[u];i;i-=i&-i) tmp1[++t1]=rt[i];
    for (int i=dfn[v];i;i-=i&-i) tmp1[++t1]=rt[i];
    int lca=getlca(u,v);
    for (int i=dfn[lca];i;i-=i&-i) tmp2[++t2]=rt[i];
    for (int i=dfn[fa[lca]];i;i-=i&-i) tmp2[++t2]=rt[i];
    return Query(1,len,k);
}
int main()
{
    n=gi();m=gi();
    for (int i=1;i<=n;++i) val[i]=o[++len]=gi();
    for (int i=1;i<n;++i)
    {
        int u=gi(),v=gi();
        link(u,v);link(v,u);
    }
    for (int i=1;i<=m;++i)
    {
        q[i]=(operation){gi(),gi(),gi()};
        if (q[i].k==0) o[++len]=q[i].b;
    }
    sort(o+1,o+len+1);len=unique(o+1,o+len+1)-o-1;
    for (int i=1;i<=n;++i)
        val[i]=lower_bound(o+1,o+len+1,val[i])-o;
    for (int i=1;i<=m;++i)
        if (q[i].k==0) q[i].b=lower_bound(o+1,o+len+1,q[i].b)-o;
    dfs1(1,0);cnt=0;dfs2(1,1);
    for (int i=1;i<=n;++i)
        PreModify(dfn[i],val[i],1),PreModify(dfn[i]+sz[i],val[i],-1);
    for (int i=1;i<=m;++i)
    {
        if (q[i].k==0)
        {
            PreModify(dfn[q[i].a],val[q[i].a],-1);
            PreModify(dfn[q[i].a]+sz[q[i].a],val[q[i].a],1);
            val[q[i].a]=q[i].b;
            PreModify(dfn[q[i].a],val[q[i].a],1);
            PreModify(dfn[q[i].a]+sz[q[i].a],val[q[i].a],-1);
        }
        else
        {
            int emm=dep[q[i].a]+dep[q[i].b]-2*dep[getlca(q[i].a,q[i].b)]+1;
            if (q[i].k>emm) puts("invalid request!");
            else printf("%d\n",o[PreQuery(q[i].a,q[i].b,q[i].k)]);
        }
    }
    return 0;
}

[HNOI2016]网络

题面

#include<cstdio>
#include<algorithm>
#include<queue>

using namespace std;

const int MAX=200005;

struct segment_tree
{
    priority_queue<int>num,del;
    void PUSH(int x,int type)
    {
        if (!type) num.push(x);
        else del.push(x);
    }
    int TOP()
    {
        while (!del.empty()&&num.top()==del.top()) num.pop(),del.pop();
        if (!num.empty()) return num.top();
        return -1;
    }
}t[MAX<<2];
struct event{int u,v,val;}sth[MAX];
struct edge{int to,next;}a[MAX<<1];
struct interval{int l,r;}qu[MAX];
int head[MAX],fa[MAX],dep[MAX],sz[MAX],son[MAX],top[MAX],dfn[MAX];
int n,m,cnt;

int gi()
{
    int x=0,w=1;char ch=getchar();
    while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    if (ch=='-') w=-1,ch=getchar();
    while (ch>='0'&&ch<='9')
    {
        x=(x<<3)+(x<<1)+ch-'0';
        ch=getchar();
    }
    return x*w;
}

bool cmp(interval x,interval y)
{
    return x.l<y.l;
}

void Link(int u,int v)
{
    a[++cnt]=(edge){v,head[u]};
    head[u]=cnt;
}

void dfs1(int u,int f)
{
    fa[u]=f;dep[u]=dep[f]+1;sz[u]=1;
    for (int e=head[u];e;e=a[e].next)
    {
        int v=a[e].to;
        if (v==f) continue;
        dfs1(v,u);
        sz[u]+=sz[v];
        if (sz[v]>sz[son[u]]) son[u]=v;
    }
}
void dfs2(int u,int up)
{
    top[u]=up;dfn[u]=++cnt;
    if (son[u]) dfs2(son[u],up);
    for (int e=head[u];e;e=a[e].next)
    {
        int v=a[e].to;
        if (v==fa[u]||v==son[u]) continue;
        dfs2(v,v);
    }
}

void Modify(int now,int l,int r,int ql,int qr,int val,int type)
{
    if (l>=ql&&r<=qr)
    {
        t[now].PUSH(val,type);
        return;
    }
    int mid=l+r>>1;
    if (ql<=mid) Modify(now<<1,l,mid,ql,qr,val,type);
    if (qr>mid) Modify(now<<1|1,mid+1,r,ql,qr,val,type);
}

int Query(int now,int l,int r,int pos)
{
    if (l==r) return t[now].TOP();
    int mid=l+r>>1,res=t[now].TOP();
    if (pos<=mid) res=max(res,Query(now<<1,l,mid,pos));
    else res=max(res,Query(now<<1|1,mid+1,r,pos));
    return res;
}

void Work(int u,int v,int val,int type)
{
    cnt=0;
    while (top[u]!=top[v])
    {
        if (dep[top[u]]<dep[top[v]]) swap(u,v);
        qu[++cnt]=(interval){dfn[top[u]],dfn[u]};
        u=fa[top[u]];
    }
    if (dep[u]>dep[v]) swap(u,v);
    qu[++cnt]=(interval){dfn[u],dfn[v]};
    sort(qu+1,qu+cnt+1,cmp);
    qu[0].r=0;qu[++cnt].l=n+1;
    for (int i=1;i<=cnt;i++) if (qu[i].l-qu[i-1].r>=2) Modify(1,1,n,qu[i-1].r+1,qu[i].l-1,val,type);
}

int main()
{
    n=gi();m=gi();
    for (int i=1;i<n;i++)
    {
        int u=gi(),v=gi();
        Link(u,v);Link(v,u);
    }
    dfs1(1,0);cnt=0;dfs2(1,1);
    for (int i=1;i<=m;i++)
    {
        int type=gi();
        if (!type)
        {
            int u=gi(),v=gi(),val=gi();
            sth[i]=(event){u,v,val};
            Work(u,v,val,type);
        }
        else if (type==1)
        {
            int k=gi();
            Work(sth[k].u,sth[k].v,sth[k].val,type);
        }
        else
        {
            int u=gi();
            printf("%d\n",Query(1,1,n,dfn[u]));
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/zhoushuyu/p/8496290.html

时间: 2024-10-11 10:40:04

树套树乱讲的代码的相关文章

树套树乱讲

树套树乱讲 树状数组套线段树 先学会主席树. 主席树可以被理解为一个二维平面,其中n棵树可以视作横轴,每棵树中的坐标范围(也就是线段树的坐标范围)可以视作纵轴.这样一来就是用主席树维护了一些在二维平面上的点,给定\(a,b,c,d\),可以在\(O(\log{n})\)的时间内求出满足\(a\le x_i\le b,c\le y_i\le d\)的\(i\)的数量. 而树状数组套线段树就是把这个问题动态化. 对于上述的问题,我们是通过对主席树直接维护前缀和,查询时两棵主席树相减,再在区间\([c

[BZOJ3110] [Zjoi2013] K大数查询 (树套树)

Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少. Input 第一行N,M 接下来M行,每行形如1 a b c或2 a b c Output 输出每个询问的结果 Sample Input 2 5 1 1 2 1 1 1 2 2 2 1 1 2 2 1 1 1 2 1 2 3 Sample Output 1 2 1 HINT [

BZOJ3295 动态逆序对 树套树, 树状数组套线段树(主席树)

Orz黄学长,蒟蒻在黄学长的带领下,通过阅读黄学长的代码!终于会了这道题! 首先我想先说一下这道题的思路(准确来说是黄学长的). 很明显,树状数组应该不用讲吧!关键是内存怎么开,维护一些什么样的数据? 其实我们通过观察,很快可以发现,你维护被删的数比维护所有的数轻松多了(不管是空间上,还是时间上).所以我们就可以从这方面想!(其实我一开始的思路,因为这道题我已经看过很久了,一直想写,毕竟是白书里面的一道例题嘛!一开始,蒟蒻的我是打算这样的用树状数组套权值线段树,并且是维护所有的数,我发现空间不够

[树套树]K大数查询

有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数是多少.为了强制在线,每一次的a,b是加密的,需要异或lastans的后8位进行解密,其中lastans为上次输出的结果,初始为零.如果解密后a>b则先交换a,b数据保证解密后a,b不会超过N如果解密后a,b出现0,则赋值为1. 来历:bzoj上的一道题,经过子祯学长的魔改后,数据范围变得很奇怪... 算法:树

ZOJ 2112 Dynamic Rankings(主席树套树状数组+静态主席树)

题意:给定一个区间,求这个区间第k大的数,支持单点修改. 思路:主席树真是个神奇的东西.........速度很快但是也有一个问题就是占用内存的很大,一般来说支持单点修改的主席树套树状数组空间复杂度为O(n*logn*logn), 如果查询较少的话,可以初始的时候用一颗静态主席树,这样空间复杂度可以降为O(n*logn+q*logn*logn),勉强可以过zoj这道题. 这道题看了好久好久才懂...网上题解一般就几句话.......下面是自己的一些理解. 首先静态主席树这个东西其实比较好懂,就是对

树套树三题 题解

1.COGS 1534 [NEERC 2004]K小数 其实是主席树裸题…… (其实这题数据非常水……从O(nlogn)的主席树到O(nlog3n)的树套树+二分到O(nsqrt(n)log2n)的分块套二分套二分到O(n2)的暴力都能过……) 鉴于这就是动态排名系统的静态版,就不说了,贴代码: 线段树套平衡树: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; con

Luck and Love (二维线段树)(树套树)

Luck and Love Problem Description 世界上上最远的距离不是相隔天涯海角 而是我在你面前 可你却不知道我爱你 ―― 李丹妮 前段日子,枫冰叶子给Wiskey做了个征婚启事,聘礼达到500万哦,天哪,可是天文数字了啊,不知多少MM蜂拥而至,顿时万人空巷,连扫地的大妈都来凑热闹来了.―_―||| 由于人数太多,Wiskey实在忙不过来,就把统计的事情全交给了枫冰叶子,自己跑回家休息去了.这可够枫冰叶子忙的了,他要处理的有两类事情,一是得接受MM的报名,二是要帮Wiske

【BZOJ3110】【Zjoi2013】K大数查询 树套树 权值线段树套区间线段树

#include <stdio.h> int main() { puts("转载请注明出处谢谢"); puts("http://blog.csdn.net/vmurder/article/details/43020009"); } 题解: 外层权值线段树,内层区间线段树可解. 权值都是1~n,就不用离散化了. 我写了标记永久化. 其它心得神马的: 天生对树形数据结构无爱. 第一次写树套树,终于知道是怎么回事了. (只针对本题) 就是外层每个点都表示了一段

BZOJ 3110 K大数查询 树套树

题意:链接 方法:树套树(线段树套线段树) 题解:这题好神啊- -自己在做的时候一顿yy也没yy出用两个线段树来搞,其实我想的是类似二逼那道题那样,用线段树维护总区间,treap维护每个节点,不过这样的话,尼玛修改就是暴力有没有?而且查询的时候也是暴力啊有没有?绝壁不是这么做的啊! 上网上找了找题解综合了大家的思想自己也是懂了这题是咋回事了,也是跪了. 好不扯淡了,谈正经的,两个线段树是怎么搞得. 其实第一棵线段树是区间的线段树,而第二棵是维护值域的线段树,具体解析请看代码. #include