首页 > 其他分享 >整体二分

整体二分

时间:2025-01-17 11:23:11浏览次数:1  
标签:二分 return int 整体 tp back query op

个人认为就是爆改cdq。

大体思路和 cdq 相同:

  • 每次递归传入操作集合 op 和区间 \([l,r]\),表示修改操作的修改位置以及查询操作的答案都位于 \([l,r]\) 内$;
  • 统计左区间修改对全区间查询的贡献;
  • 判断查询应下放到左右哪个区间;
  • 分割操作至左右两区间

例题

海亮 OJ 题单

P3834 【模板】可持久化线段树 2

#include<iostream>
#include<vector>
using namespace std;
const int N = 2E5 + 10;
const int A = 1e9;

struct Op {
	int x, y, k;
	int id, tp;
};

int n, Q;
int ans[N];

namespace BIT {
	int sum[N];
	inline int lowbit(int x) { return x & -x; }
	inline void modify(int p, int v) {
		for(int i = p; i <= n; i += lowbit(i)) {
			sum[i] += v;
		}
	}
	inline int query(int p) {
		int res = 0;
		for(int i = p; i > 0; i -= lowbit(i)) {
			res += sum[i];
		}
		return res;
	}
	inline int query(int l, int r) {
		return query(r) - query(l - 1);
	}
}

void solve(vector<Op> &op, int l, int r) {
	if(op.empty()) return;
	if(l == r) {
		for(Op o : op) {
			if(o.tp == 0) {
				ans[o.id] = l;
			}
		}
		return;
	}
	int mid = (l + r) >> 1;
	for(Op o : op) {
		if(o.tp == 1 && o.x <= mid) BIT::modify(o.id, 1); 
	}
	vector<Op> lop, rop;
	for(Op o : op) {
		if(o.tp == 0) {
			int cnt = BIT::query(o.x, o.y);
			if(cnt >= o.k) lop.push_back(o);
			else rop.push_back({o.x, o.y, o.k - cnt, o.id, o.tp});
		} else {
			if(o.x <= mid) lop.push_back(o);
			else rop.push_back(o); 
		}
	}
	for(Op o : op) {
		if(o.tp == 1 && o.x <= mid) BIT::modify(o.id, -1);
	}
	solve(lop, l, mid);
	solve(rop, mid + 1, r);
}

vector<Op> op;

int main() {
	
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	
	cin >> n >> Q;
	for(int i = 1; i <= n; i++) {
		int x;
		cin >> x;
		op.push_back({x, 0, 0, i, 1}); 
	}
	for(int i = 1; i <= Q; i++) {
		int l, r, k;
		cin >> l >> r >> k;
		op.push_back({l, r, k, i, 0});
	}
	
	solve(op, -A, A);
	
	for(int i = 1; i <= Q; i++) {
		cout << ans[i] << '\n'; 
	}
	
	return 0;
}

P2617 Dynamic Rankings

#include<iostream>
#include<vector>
using namespace std;
const int N = 1E5 + 10;
const int A = 1E9; 

struct Op {
	int x, y, k;
	int id, tp;
};

int n, m;
int ans[N];

namespace BIT {
	int sum[N];
	inline int lowbit(int x) { return x & -x; }
	inline void modify(int p, int v) {
		for(int i = p; i <= n; i += lowbit(i)) {
			sum[i] += v;
		} 
	}
	inline int query(int p) {
		int res = 0;
		for(int i = p; i > 0; i -= lowbit(i)) {
			res += sum[i];
		}
		return res;
	} 
	inline int query(int l, int r) {
		return query(r) - query(l - 1);
	}
}

void cdq(vector<Op>& op, int l, int r) {
	if(op.empty()) return; 
	if(l == r) {
		for(Op o : op) {
			if(o.tp == 0) ans[o.id] = l;
		}
		return;
	}
	int mid = (l + r) >> 1;
	vector<Op> lop, rop;
	for(Op o : op) {
		if(o.tp == 0) {
			int lcnt = BIT::query(o.x, o.y);
			if(o.k <= lcnt) lop.push_back(o);
			else rop.push_back({o.x, o.y, o.k - lcnt, o.id, o.tp}); 
		} else if(o.x <= mid) {
			BIT::modify(o.id, o.tp);
			lop.push_back(o);
		} else {
			rop.push_back(o);
		}
	}
	for(Op o : op) {
		if(o.tp && o.x <= mid) {
			BIT::modify(o.id, -o.tp);
		}
	}
	cdq(lop, l, mid);
	cdq(rop, mid + 1, r);
} 

int a[N];
vector<Op> op;

int main() {
	
	cin >> n >> m;
	for(int i = 1; i <= n; i++) {
		cin >> a[i];
		op.push_back({a[i], 0, 0, i, 1});
	}
	
	int nq = 0;
	while(m--) {
		char c;
		int l, r, x, y, k;
		cin >> c;
		if(c == 'Q') {
			cin >> l >> r >> k;
			op.push_back({l, r, k, ++nq, 0}); 
		} else {
			cin >> x >> y;
			op.push_back({a[x], 0, 0, x, -1});
			op.push_back({y, 0, 0, x, 1});
			a[x] = y;
		}
	}
	
	cdq(op, 0, A);
	
	for(int i = 1; i <= nq; i++) {
		cout << ans[i] << '\n';
	}
	
	return 0;
} 

标签:二分,return,int,整体,tp,back,query,op
From: https://www.cnblogs.com/SimonHTC/p/18676489

相关文章

  • 二分
    1.解释其实这个东西吧,是分治的分支优点:时间复杂度低,十分简单,方便写,适用绝大多数题目缺点:总有人眼瞎写错()2.步骤1.在序列中确定中间数2.判断这数是不是,\(<\)的话去左边找,否则去右边找3.重复步骤直到中间数是要求的数字3.例题题目:洛谷P1873方法:朴素算法查找肯定超时,......
  • 二分查找算法的3种模板-PYTHON
    classbinary_search(object):def__init__(self,nums,target):self.nums=numsself.target=targetdefbinary_search_template_1(self):iflen(self.nums)==0:return-1l,r=0,len(self.nums)-1......
  • 搜索与图论(三)-最小生成树(Prim、Kruskal)和二分图(染色法、匈牙利法)
    目录一、最小生成树1.Prim算法 2.Kruskal算法二、二分图  1.判断二分图--染色体法 2.求二分图最大匹配--匈牙利算法一、最小生成树1.Prim算法         分为朴素Prim算法和堆优化Prim算法。写法和dijikstra算法类似,堆优化过程也类似,可类比学习。首......
  • git整体使用流程
    一、场景说明本地有文件想在github创建一个远程仓库在本地修改,同时同步到远端二、流程设置用户名和邮箱目的:标识每次提交者的身份设置全局用户名:gitconfig--globaluser.name"YourName"设置全局邮箱:gitconfig--globaluser.email"your.email@example.com"......
  • day01 704. 二分查找&&27. 移除元素
    二分查找(search方法)publicintsearch(int[]nums,inttarget){intleft=0;intright=nums.length-1;intmid;while(left<=right){mid=(left+right)/2;if(nums[mid]==target){returnmid;}elseif(nums[mid]<target){left=mid+1;}else{right=mid-1;}}retur......
  • 【LeetCode 刷题】二分搜索
    此博客作为《代码随想录》的学习笔记,主要内容为二分搜索法及相关题目解析。文章目录704.二分查找35.搜索插入位置34.在排序数组中查找元素的第一个和最后一个位置69.x的平方根367.有效的完全平方数以下所有二分法算法均基于左闭右闭区间704.二分查找LeetCode......
  • 信息系统项目管理师2025年考试关键知识点梳理-第8章 项目整合管理-制定项目管理计划、
    1、制定项目管理计划制订项目管理计划是定义、准备和协调项目计划的所有组成部分,并把它们整合为一份综合项目管理计划的过程。本过程的主要作用:生成一份综合文件,用于确定所有项目工作的基础及其执行方式。项目管理计划确定项目的执行、监控和收尾方式,其内容会根据项目所在......
  • 树状数组【单点修改+区间查询】+二分
    https://codeforces.com/gym/580226/problem/H#include<bits/stdc++.h>usingnamespacestd;#defineendl'\n'#definelowbit(x)x&(-x)usingll=longlong;usingpii=pair<int,int>;constdoublePI=acos(-1);constintN=2e5......
  • 算法-在数组中获取制定值的索引值-php(二分法)
    算法-在数组中获取制定值的索引值-php(二分法)<?php/***代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可***@paramnumsint整型一维数组*@paramtargetint整型*@returnint整型*/functionsearch($nums,$target){//......
  • 为AI聊天工具添加一个知识系统 之30 概念整体运营平台:中间架构层的broker service的AP
    本文要点本项目(为AI聊天工具增加知识系统)通过完善“公路”的整体概念框架 最终(在外部)为三类公共运营性交通工具((高速-轿车taxi/中速--公交车bus/低速-卡车truck))提供运营平台。该平台对内通过明确交通路线上的三种“端”(end/stop/start)的一般术语框架作为程序的形式化规......