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;
    }
    
  • 相关阅读:
    mongo与node的两种连接方式 mongoskin && mongoclient 的基本使用
    promise 源码 简单分析
    node之 glob模块 相对路径绝对路径浅析
    webpack 多入口打包配置示例
    webpack 多入口打包分析
    MyEclipse8.5 以debug模式启动tomcat6.0服务器 报错cannot connect to vm。
    java开发bug 在启动Tomcat 6.0时发现第一条信息便是
    java 开发, jdk 1.6 官方下载地址
    电脑故障
    myeclipse添加源码支持
  • 原文地址:https://www.cnblogs.com/lyttt/p/14067177.html
Copyright © 2011-2022 走看看