首页 > 其他分享 >[OI] 偏序

[OI] 偏序

时间:2024-08-09 17:39:02浏览次数:11  
标签:偏序 node return val OI int mid now

\(n\) 维偏序即给出若干个点对 \((a_{i},b_{i},\cdots,n_{i})\),对每个 \(i\) 求出满足 \(a_{j}\gt a_{i},b_{j}\gt b_{i}\cdots,n_{j}\gt n_{i}\) 的 \(j\) 的个数

一维偏序

直接用权值线段树或者树状数组. 或者你直接离散化开桶前缀和.

二维偏序

考虑到先对全部点对按 \(a_{i}\) 排序,这样,任何点对只能被它前面的点产生贡献.

a 1 1 1 2 3 4 4 5
b 1 2 3 3 4 2 4 1

可以发现,\(i\) 处的答案可以转化为:其前方的点中满足一维偏序的点数.

所以我们考虑对点对从左到右扫一遍,每次向维护的动态树状数组中加入一个新节点,统计前缀和即可.

三维偏序

CDQ+数据结构 解法

按二维偏序的套路,先对 \(a_{i}\) 排序

然后我们考虑这样分解问题:向下对 \(b\) 进行归并排序,每次只统计 \(i\in[l,mid],j\in[mid+1,r]\) 的答案. 可以发现,对于区间内部的答案,总会有递归下去的子区间来求解,对于区间之间的答案,当前这一步将会求解出来,因此我们恰好统计了所有答案,这就是 CDQ 分治.

为什么我们在进行统计答案的时候需要对 \(b\) 排序?假设现在两个子区间内的 \(b\) 都是有序的(\(a\) 是完全有序的,我们不管它),那么在对 \(b\) 归并排序的过程中,会发现,只有 \(i\) 能对 \(j\) 产生贡献(因为 \(a\) 数组的限制),并且只有 \(i\) 数对的 \(b\) 比 \(j\) 数对的 \(b\) 更小的时候,\(i\) 才可能对 \(j\) 有贡献,表现在归并排序里就是只有比 \(j\) 先选的 \(i\) 才能对 \(j\) 有贡献. 基于这一点,我们才能用树状数组+CDQ分治来解决偏序问题.

#include<bits/stdc++.h>
using namespace std;
#define p &
int n,k;
struct node{
	int a,b,c;
	int cnt,res;
	bool operator !=(const node &A)const{
		return a!=A.a or b!=A.b or c!=A.c;
	}
};
node e[100001];
node ue[100001];
int m,t;
int res[100001];
struct bit{
	int a[200001];
	function<int(int)> lowbit=[](int x){return x&-x;};
	inline void add(int pos,int val){
		while(pos<=k){
			a[pos]+=val;
			pos+=lowbit(pos);
		}
	};
	inline int ask(int pos){//sum[pos]
		int res=0;
		while(pos){
			res+=a[pos];
			pos-=lowbit(pos);
		}
		return res;
	};
}BIT;
bool cmp1(node a,node b){
	if(a.a!=b.a) return a.a<b.a;
	if(a.b!=b.b) return a.b<b.b;
	return a.c<b.c;
}
bool cmp2(node a,node b){
	if(a.b!=b.b) return a.b<b.b;
	return a.c<b.c;
}
void cdq(int l,int r){
	if(l==r) return;//i!=j 单个区间无法产生贡献 
	int mid=(l+r)/2;
	cdq(l,mid);//递归求解子区间 
	cdq(mid+1,r);
	sort(ue+l,ue+mid+1,cmp2);//按 b 排序,方便归并 
	sort(ue+mid+1,ue+r+1,cmp2);
	int i=l,j=mid+1;//归并排序 
	//注意这里并不会真的排序,因为父区间会有 sort 的 
	while(j<=r){
		while(i<=mid and ue[i].b<=ue[j].b){
			//当前 i 更小,将会对 j 与 j 后方的位置产生贡献 
			BIT.add(ue[i].c,ue[i].cnt);
			i++;
		}
		//后面的 i 值不再能够产生贡献了,此时暂时统计答案 
		ue[j].res+=BIT.ask(ue[j].c);
		j++;
	}
	for(int k=l;k<=i-1;++k){
		BIT.add(ue[k].c,-ue[k].cnt);
		//清空 BIT,memset 也行就是有点慢 
	}
}
int main(){
	scanf("%d %d",p n,p k);
	for(int i=1;i<=n;++i){
		scanf("%d %d %d",p e[i].a,p e[i].b,p e[i].c);
	}
	sort(e+1,e+n+1,cmp1);
	for(int i=1;i<=n;++i){
		t++;
		if(e[i]!=e[i+1]){
			//去重,防止相同的元素统计不到而漏答案 
			ue[++m]={e[i].a,e[i].b,e[i].c,t};
			t=0;
		}
	}
	cdq(1,m);
	for(int i=1;i<=m;++i){
		//去重在这里用到了 
		res[ue[i].res+ue[i].cnt-1]+=ue[i].cnt;
	}
	for(int i=0;i<=n-1;++i){
		printf("%d\n",res[i]);
	}
}

数据结构+数据结构

众所周知,三维偏序可以用树套树来解决.

我并不是非常喜欢写树套树,因此就写了一个树套树

我说怎么没人线段树套线段树,原来是会 TLE 啊,哈哈哈

标签:偏序,node,return,val,OI,int,mid,now
From: https://www.cnblogs.com/HaneDaCafe/p/18351138

相关文章

  • Android dex、odex、oat、vdex、art区别
    1.dexjava程序编译成class后,dx工具将所有class文件合成一个dex文件,dex文件是jar文件大小的50%左右.2.odex(Android5.0之前)全称:OptimizedDEX;即优化过的DEX.Android5.0之前APP在安装时会进行验证和优化,为了校验代码合法性及优化代码执行速度,验证和优化后,会产生ODEX文件,运行Apk的......
  • P5975 [CEOI2009] photo
    题目链接。可过掉帖子中的所有Hack数据。Analysis\(f_{l,r,p}\)表示覆盖了\([l,r]\)区间内纵坐标\(\gep\)的点最矩形个数(离散化后)。那么就有转移:\[f_{l,r,p}=\min(f_{l,r,p},f_{l,mid,p}+f_{mid+1,r,p})\]\[f_{l,r,p}=\min(f_{l,r,p},f_{l,r,res}+1)\]令\(h......
  • ComfyUI插件:ComfyUI_Noise节点
    前言:学习ComfyUI是一场持久战,ComfyUI_Noise是对ComfyUI中的噪声进行控制的一个插件库,该库可以完成图像噪声的反推,并通过采样再以几乎无损的方式返回原图,通过该库的使用可以更好的帮助图像恢复原始的相貌,非常适合在生成视频领域用作人物转绘使用。祝大家学习顺利,早日成为ComfyUI的......
  • Local All-Pair Correspondence for Point Tracking 中英对照
    论文来自:https://ku-cvlab.github.io/locotrack/LocalAll-PairCorrespondenceforPointTracking局部全对应对点跟踪SeokjuCho\({}^{1}\),JiahuiHuang\({}^{2}\),JisuNam\({}^{1}\),HonggyuAn\({}^{1}\),Seungryong\({\mathrm{{Kim}}}^{1,\dagger}\),......
  • P4281 [AHOI2008] 紧急集合 / 聚会
    题意给出3个点,选出一个点使得3个点到这个点的距离之和最小。思路三个点可以先取2个点的lca,然后与第3个点再取lca。三个点的两两求lca,至多只会有2个不同的结点。三个点的距离\(dis[x]+dis[y]+dis[z]-dis[lca(a,b)]-dis[lca(b,c)]-dis[lca(a,b)]\)......
  • 高通C6490 android13 GMS 认证之CtsCarrierApiTestCases
    我们机器是没有SIM卡的,只需要连接wifi。跑CTS测试,CtsCarrierApiTestCases的测试结果都是报没有SIM卡的错误。如下:android.carrierapi.cts.ApnDatabaseTest#testQueryConflictCase fail ThistestrequiresaSIMcardwithcarrierprivilegerulesonit. 解决方法:需要......
  • Java计算机毕业设计基于Android手机个人日记本(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景在快节奏的现代生活中,个人情感的记录与表达成为了许多人寻求心灵慰藉的重要方式。随着智能手机的普及和移动互联网技术的飞速发展,移动应用成为了人们......
  • Java计算机毕业设计基于android的健身运动app演示录像220239(开题报告+源码+论文)
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着现代生活节奏的加快,健康问题日益受到人们的关注。健身运动作为一种积极的生活方式,不仅能够增强体质、提高免疫力,还能有效缓解工作与生活带来的压......
  • NOIP模拟 三元子序列计数
    题意给一个长度为\(n\)的排列\(a\),和一个\(3\)的排列\(p\)。求问\(a\)有多少长度为\(3\)的子序列,满足将其中的元素从小到大编号后为\(p\)。思路仔细手玩一下会发现很难找到一个对于任意\(p\)的通解,实际上\(p\)的情况可以做一些合并:原\(p\)归约方法(对于\(......
  • SQL Zoo 7.More JOIN operations
    以下数据均来自SQLZoo1.Listthefilmswherethe yr is1962[Show id, title](列出1962年的电影)SELECTid,titleFROMmovieWHEREyr=19622.Giveyearof'CitizenKane'.(给出《公民凯恩》的年份)selectyrfrommoviewheretitle='CitizenKane'3.List......