zoukankan      html  css  js  c++  java
  • 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();
    	}
    }
    
  • 相关阅读:
    forceStopPackage应用中关闭其他应用程序
    Android为什么选择binder
    Ril分析一——rild进程
    Ril分析五——ril学习总结
    Binder基本概念流程学习
    Ril分析四——来自网络端事件流程
    inno setup详细使用教程
    如何下载mysql 5.5.32 二进制包
    eclipse搭建springboot开发环境
    “STO”是“Store”的缩写,意思是“商场”
  • 原文地址:https://www.cnblogs.com/weiyanpeng/p/13766669.html
Copyright © 2011-2022 走看看