zoukankan      html  css  js  c++  java
  • CF1132G Greedy Subsequences【dfs序-线段树】

    题目链接

    题目解析

    注意到每个数的后继都是唯一的。

    那么我们可以把这个序列挂到树上去,每个点的后继就是父节点。用类似于笛卡尔树的方式建树。

    那么题目要求的最长贪心严格上升子序列的长度就是从儿子到父亲的最长链的长度。

    题目有给定区间并修改,而如果区间中新出现一个数(a[x]),那么它子树内的所有结点的答案都会(+1),同样地,如果去掉这个数,它子树内的所有结点的答案都会(-1)。而一棵树又可以通过(dfs)序变成一个序列,所以可以用线段树维护区间加和区间最大值。

    注意一点就是建树的时候要加个(n+1)上去,保证把所有的点都搞上树(相当于给个根,把所有最长贪心严格上升子序列的末尾的数并起来。


    ►Code View

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    #define N 1000005
    #define MOD 998244353
    #define INF 0x3f3f3f3f
    int rd()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
    	return f*x;
    }
    struct node{
    	int mx,tag;
    }tree[N<<2];
    int n,k,a[N],stk[N],tp;
    vector<int>G[N];
    int dfn[N],tim,siz[N];
    void dfs(int u)
    {
    	dfn[u]=++tim;
    	siz[u]=1;
    	for(int i=0;i<G[u].size();i++)
    	{
    		int v=G[u][i];
    		dfs(v);
    		siz[u]+=siz[v];
    	}
    }
    void PushDown(int i)
    {
    	if(tree[i].tag)
    	{
    		tree[i<<1].mx+=tree[i].tag;
    		tree[i<<1].tag+=tree[i].tag;
    		tree[i<<1|1].mx+=tree[i].tag;
    		tree[i<<1|1].tag+=tree[i].tag;
    		tree[i].tag=0;
    	}
    }
    void PushUp(int i)
    {
    	tree[i].mx=max(tree[i<<1].mx,tree[i<<1|1].mx);
    }
    void Update(int i,int l,int r,int ql,int qr,int val)
    {
    	if(ql<=l&&r<=qr)
    	{
    		tree[i].mx+=val;
    		tree[i].tag+=val;
    		return ;
    	}
    	PushDown(i);
    	int mid=(l+r)>>1;
    	if(ql<=mid) Update(i<<1,l,mid,ql,qr,val);
    	if(qr>mid) Update(i<<1|1,mid+1,r,ql,qr,val);
    	PushUp(i);
    }
    int main()
    {
    	n=rd(),k=rd();
    	for(int i=1;i<=n;i++)
    		a[i]=rd();
    	for(int i=1;i<=n;i++)
    	{//维护一个单调栈 找到每个数右边第一个比自己大的数 
    		while(tp&&a[stk[tp]]<a[i])
    		{
    			G[i].push_back(stk[tp]);//i是stk[tp]的爸爸
    			tp--;
    		}
    		stk[++tp]=i;
    	}
    	while(tp)
    	{
    		G[n+1].push_back(stk[tp]);
    		tp--;
    	}
    	dfs(n+1);
    	for(int i=1;i<=k;i++)
    		Update(1,1,n+1,dfn[i],dfn[i]+siz[i]-1,1);
    	printf("%d ",tree[1].mx);
    	for(int i=k+1;i<=n;i++)
    	{
    		Update(1,1,n+1,dfn[i],dfn[i]+siz[i]-1,1);
    		Update(1,1,n+1,dfn[i-k],dfn[i-k]+siz[i-k]-1,-1);
    		printf("%d ",tree[1].mx);
    	} 
    	return 0;
    }
    
  • 相关阅读:
    BZOJ 1977: [BeiJing2010组队]次小生成树 Tree( MST + 树链剖分 + RMQ )
    BZOJ 2134: 单选错位( 期望 )
    BZOJ 1030: [JSOI2007]文本生成器( AC自动机 + dp )
    BZOJ 2599: [IOI2011]Race( 点分治 )
    BZOJ 3238: [Ahoi2013]差异( 后缀数组 + 单调栈 )
    ZOJ3732 Graph Reconstruction Havel-Hakimi定理
    HDU5653 Bomber Man wants to bomb an Array 简单DP
    HDU 5651 xiaoxin juju needs help 水题一发
    HDU 5652 India and China Origins 并查集
    HDU4725 The Shortest Path in Nya Graph dij
  • 原文地址:https://www.cnblogs.com/lyttt/p/14067177.html
Copyright © 2011-2022 走看看