IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> Range and Partition (贪心+双指针) -> 正文阅读

[数据结构与算法]Range and Partition (贪心+双指针)

D. Range and Partition

[Link](D. Range and Partition)

题意

给你一个长为 n n n的数组,让你分成 k k k段,满足每段在 [ x , y ] [x,y] [x,y]内的严格大于在在 [ x , y ] [x,y] [x,y]外的,请你最小化 y ? x y-x y?x并输出切割方案。

思路

c n t 1 : 在 [ x , y ] 内 的 个 数 , c n t 2 : 不 在 [ x , y ] 内 的 个 数 , f ( l , r ) : 原 数 组 a [ l ] , a [ l + 1 ] , . . . , a [ r ] 中 c n t 1 ? c n t 2 的 值 cnt1:在[x,y]内的个数,cnt2:不在[x,y]内的个数,f(l,r):原数组a[l],a[l+1],...,a[r]中cnt1-cnt2的值 cnt1[x,y]cnt2[x,y]f(l,r)a[l],a[l+1],...,a[r]cnt1?cnt2

f ( ) f() f()的性质: 1. f ( l , r ) > 0 则 该 区 间 一 定 满 足 条 件 , 2. f ( l , r ) = ( l , m i d ) + ( m i d + 1 , r ) 满 足 合 并 1.f(l,r)>0则该区间一定满足条件,2.f(l,r) = (l,mid)+(mid+1,r)满足合并 1.f(l,r)>02.f(l,r)=(l,mid)+(mid+1,r)

f ( l , r ) > 0 , 不 妨 设 f ( l , r ) = = k , f(l,r)>0,不妨设f(l,r)==k, f(l,r)>0f(l,r)==k则该区间可分为 k k k个满足条件的区间。

证明:

首先设 f ( l , r ) = = k > 0 f(l,r)==k>0 f(l,r)==k>0,如有一个位置 x x x使得 f ( l , x ) = = 1 f(l,x)==1 f(l,x)==1,那么我们就可以从这个位置切割,使得 f ( x + 1 , r ) = = k ? 1 f(x +1,r)==k-1 f(x+1,r)==k?1

又因为 f ( l , l ? 1 ) = = 0 f(l,l-1)==0 f(l,l?1)==0,(空区间无意义),且 f ( l , r ) = = k f(l,r)==k f(l,r)==k f ( l , x x ) → f ( l , x x + 1 ) f(l,xx)\to f(l,xx + 1) f(l,xx)f(l,xx+1)时值最多边 1 1 1,因此类似于零点存在定理,一定存在某个点 x x x满足 f ( l , x ) = = 1 f(l,x)==1 f(l,x)==1

如果我们知道想要分成 k k k段,则要满足 c n t 1 ? c n 2 = = k , c n t 1 + c n t 2 = = n → c n t 1 = ? ( n + k ) / 2 ? cnt1-cn2==k,cnt1+cnt2==n\to cnt1=\lceil (n +k)/2\rceil cnt1?cn2==k,cnt1+cnt2==ncnt1=?(n+k)/2?

因此我们可以拿双指针从头到尾扫一下值域判断一下满足条件 c n t 1 = ? ( n + k ) / 2 ? cnt1=\lceil (n +k)/2\rceil cnt1=?(n+k)/2?的最小区间,然后从头到尾暴力扫,如果当前 f ( ) = = 1 f()==1 f()==1输出这个区间即可。

Code

#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <set>
#include <queue>
#include <vector>
#include <map>
#include <bitset>
#include <unordered_map>
#include <cmath> 
#include <stack>
#include <iomanip>
#include <deque> 
#include <sstream>
#define x first
#define y second
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long double ld;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef unsigned long long ULL;
const int N = 2e5 + 10, M = 2 * N, INF = 0x3f3f3f3f, mod = 1e9 + 7;
const double eps = 1e-8, pi = acos(-1), inf = 1e20;
#define tpyeinput int
inline char nc() {static char buf[1000000],*p1=buf,*p2=buf;return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;}
inline void read(tpyeinput &sum) {char ch=nc();sum=0;while(!(ch>='0'&&ch<='9')) ch=nc();while(ch>='0'&&ch<='9') sum=(sum<<3)+(sum<<1)+(ch-48),ch=nc();}
int dx[] = {-1, 0, 1, 0}, dy[] = {0, 1, 0, -1};
int h[N], e[M], ne[M], w[M], idx;
void add(int a, int b, int v = 0) {
	e[idx] = b, w[idx] = v, ne[idx] = h[a], h[a] = idx ++;
}
int n, m, k;
int a[N], s[N];
int main() {
	ios::sync_with_stdio(false), cin.tie(0);
	int T;
	cin >> T;
	while (T -- ) {
		cin >> n >> k;
		for (int i = 1; i <= n; i ++) cin >> a[i], s[a[i]] ++;
		int len = (n + k + 1) / 2, resl = 1, resr = n, mn = n, last = 1;	
		int sum = 0;
		for (int i = 1, j = 1; i <= n; i ++) {			
			while (j <= n && sum < len) sum += s[j ++];
			if (sum < len) break;
			if (j - i < mn) {
				mn = j - i;
				resl = i, resr = j - 1;				
			}
			sum -= s[i];
		}
		
		cout << resl << ' ' << resr << endl;
		sum = 0;
		for (int i = 1; i <= n; i ++) {
			if (a[i] >= resl && a[i] <= resr) sum ++;
			else sum --;
			
			if (sum > 0)  {
				if (k != 1)
					cout << last << ' ' << i << endl;
				else {
					cout << last << ' ' << n << endl;
					break;
				} 
				last = i + 1;
				k --;	
				sum = 0;				
			}
		}
		for (int i = 1; i <= n; i ++) s[i] = 0;
	}
	return 0;
}
  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-01-29 23:20:21  更:2022-01-29 23:22:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 17:33:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码