• 树套树乱讲的代码


    树套树乱讲的代码

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

    动态区间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
    ",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
    ",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
    ",Sum(q[i].l,q[i].r,1,q[i].k-1)+1);
            if (q[i].opt==2)
                printf("%d
    ",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
    ");
                else printf("%d
    ",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
    ");
                else printf("%d
    ",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
    ",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
    ",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
    ",Query(1,1,n,dfn[u]));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    一款好用的绘图软件gnuplot
    剑指offer--18.从尾到头打印链表
    剑指offer--17.第一个只出现一次的字符
    剑指offer--16.数组中重复的数字
    剑指offer--15.把字符串转换成整数
    剑指offer--14.求1+2+3+...+n
    剑指offer--13.二进制中1的个数
    剑指offer--12.不用加减乘除做加法
    剑指offer--11.数组中出现次数超过一半的数字
    剑指offer--10.最小的K个数
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8496290.html
Copyright © 2020-2023  润新知