• CF 1408H


    题目链接

    首先可以考虑二分答案。首先不难发现的是一定有一组解不会有两组三元组满足: (i_1le i_2le k_2le i_1)

    (i,k) 显然就是选最先和最后的几个 (0)。考虑每个数字连的边,会发现如果在左边他会连向一段前缀,如果在右边会连向一段后缀。

    那么考虑霍尔定理,不难发现选择的点一定是一段区间。于是显然可以考虑扫描线过去求解,复杂度 (O(nlog ^2)),并不足以通过。

    但是仔细考虑这个线段树,会发现的是实际上线段树上的修改与查询都是一样的(或不会对答案造成影响),于是只需要做一次扫描线,复杂度(O(nlog ))

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    const int N = 5e5+5;
    int n, a[N];
    
    vector<int> zeros;
    
    int lft[N], rgt[N];
    
    #define mid ((l+r)>>1)	
    
    int tg[N<<2], mx[N<<2];
    inline void pushdown(int x,int l,int r){
    	if(tg[x]!=0)if(l^r){
    		mx[x<<1]+=tg[x],mx[x<<1|1]+=tg[x];
    		tg[x<<1]+=tg[x],tg[x<<1|1]+=tg[x];
    	}
    	tg[x] = 0;
    }
    inline void modify(int x,int l,int r,int ql,int qr,int s){
    	pushdown(x,l,r);
    	if(ql<=l&&qr>=r){
    		tg[x]+=s,mx[x]+=s;return;
    	}
    	if(ql<=mid)modify(x<<1,l,mid,ql,qr,s);
    	if(qr>mid)modify(x<<1|1,mid+1,r,ql,qr,s);
    	mx[x] = max(mx[x<<1],mx[x<<1|1]);
    }
    inline void build(int x,int l,int r){
    	tg[x] = 0;
    	if(l==r){mx[x] = -n-l;return ;}
    	build(x<<1,l,mid),build(x<<1|1,mid+1,r);
    	mx[x] = max(mx[x<<1], mx[x<<1|1]);
    }
    #undef mid
    
    inline void Main(){
    	cin >> n;
    	zeros.clear();
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		if(a[i]==0)zeros.push_back(i);
    	}
    	for(int i=1;i<=n;i++)lft[i] = rgt[i] = 0;
    	int midpoint = zeros.size()?zeros[zeros.size() / 2]:1;
    	for(int i=1,P=0;i<=midpoint;i++)
    		if(!a[i])++P;
    		else lft[a[i]]=P;
    	for(int i=n,P=0;i>midpoint;i--)
    		if(!a[i])++P;
    		else rgt[a[i]]=P;
    	vector<vector<int> > opt(n);
    	build(1,0,n);
    	for(int i=1;i<=n;i++){
    		opt[rgt[i]].push_back(lft[i]);
    	}
    	for(int r=n-1;~r;--r){
    		for(auto l: opt[r]){
    			modify(1,0,n,l,n,1);
    		}
    	}
    	int maxm = zeros.size()/2;
        for(int r=n-1;~r;--r){
    		int mm = mx[1];
    		maxm = min(maxm, -mm + r);
    		for(auto l: opt[r]){
    			modify(1,0,n,l,n,-1);
    		}
    	}
    	cout << maxm << endl;
    }
    
    int main()
    {
    	int T;cin >> T;
    	while(T--){
    		Main();
    	}
    }
    
  • 相关阅读:
    [开心一笑]学妹写的函数
    Silverlight Fundamentals
    北京火车订票电话一览
    Silverlight 2 RTW tomorrow and more goodness
    [转]什么是“29岁现象”?
    看起来很像算法问题的CSS问题
    火狐不支持innerText的解决办法
    纯JS的表单邮件发送
    抽取思维(重构设计)
    不定长参数作用
  • 原文地址:https://www.cnblogs.com/weiyanpeng/p/13766669.html
Copyright © 2020-2023  润新知