zoukankan      html  css  js  c++  java
  • 【CF1556E】Equilibrium

    题目

    题目链接:https://codeforces.com/contest/1556/problem/E
    给定两个长度为 (n) 的序列 (a,b)。一次操作可以选择一个严格递增序列 (q_1,q_2,cdots,q_k)(要求 (k) 为偶数),让 (a_{q_1},a_{q_3},cdots,a_{q_{k-1}}) 全部加 (1)(a_{q_2},a_{q_4},cdots,a_{q_{k}}) 全部减 (1)
    (Q) 次询问,每次询问给定 (l,r),求区间 ([l,r]) 这一段区间至少需要多少次操作才能把 (a_{l}sim a_r) 变为 (b_lsim b_r)
    (n,Qleq 10^5)

    思路

    首先令 (a_i= b_i-a_i)。不难发现,对于正数,我们只可能让他减;负数只可能加;零肯定不会选。这个画一下很容易证明。
    那么把正数 (v) 看作连续 (v)(,负数 (v) 看作连续 (-v)),那么对于一次询问 (l,r),它是可能的当且仅当 (lsim r) 这一段是一个合法的括号序列,并且答案就是最大的括号嵌套数。
    考虑类似区间最大子段和一般的线段树做法,维护一棵线段树,对于线段树上每一个区间维护 (ans,cnt1,cnt2),分别表示这个区间内最大括号嵌套层数;剩余没有匹配的左 / 右括号数量。
    区间合并的时候就判断一下左区间的 ( 数量和右区间的 ) 数量的大小。
    时间复杂度 (O(Qlog n))

    代码

    #include <bits/stdc++.h>
    #define pb push_back
    #define mp make_pair
    #define fi first
    #define se second
    using namespace std;
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    
    const int N=100010;
    int Q,n,a[N],b[N];
    
    struct node
    {
    	ll ans,cnt1,cnt2;
    };
    
    node merge(node x,node y)
    {
    	node z;
    	if (x.cnt1>y.cnt2)
    	{
    		z.ans=max(x.ans,y.ans+x.cnt1-y.cnt2);
    		z.cnt1=x.cnt1+y.cnt1-y.cnt2;
    		z.cnt2=x.cnt2;
    	}
    	else
    	{
    		z.ans=max(y.ans,x.ans+y.cnt2-x.cnt1);
    		z.cnt1=y.cnt1;
    		z.cnt2=x.cnt2+y.cnt2-x.cnt1;
    	}
    	return z;
    }
    
    struct SegTree
    {
    	node f[N*4];
    	
    	void update(int x,int l,int r,int k,ll v)
    	{
    		if (l==r)
    		{
    			f[x]=(node){abs(v),max(0LL,v),max(0LL,-v)};
    			return;
    		}
    		int mid=(l+r)>>1;
    		if (k<=mid) update(x*2,l,mid,k,v);
    			else update(x*2+1,mid+1,r,k,v);
    		f[x]=merge(f[x*2],f[x*2+1]);
    	}
    	
    	node query(int x,int l,int r,int ql,int qr)
    	{
    		if (ql==l && qr==r) return f[x];
    		int mid=(l+r)>>1;
    		if (qr<=mid) return query(x*2,l,mid,ql,qr);
    		if (ql>mid) return query(x*2+1,mid+1,r,ql,qr);
    		return merge(query(x*2,l,mid,ql,mid),query(x*2+1,mid+1,r,mid+1,qr));
    	}
    }seg;
    
    int main()
    {
    	scanf("%d%d",&n,&Q);
    	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    	for (int i=1;i<=n;i++) scanf("%d",&b[i]);
    	for (int i=1;i<=n;i++) seg.update(1,1,n,i,b[i]-a[i]);
    	while (Q--)
    	{
    		int l,r;
    		scanf("%d%d",&l,&r);
    		node res=seg.query(1,1,n,l,r);
    		if (res.cnt1 || res.cnt2) cout<<"-1
    ";
    			else cout<<res.ans<<"
    ";
    	}
    	return 0;
    }
    
  • 相关阅读:
    670. Maximum Swap
    653. Two Sum IV
    639. Decode Ways II
    636. Exclusive Time of Functions
    621. Task Scheduler
    572. Subtree of Another Tree
    554. Brick Wall
    543. Diameter of Binary Tree
    535. Encode and Decode TinyURL
    博客园自定义背景图片
  • 原文地址:https://www.cnblogs.com/stoorz/p/15206081.html
Copyright © 2011-2022 走看看