20240201-高级数据结构总结

待办:
倍增
并查集
线段树合并
set
逆序对
树
动态开点

线段树

  • 套用模版
#include<bits/stdc++.h>
using namespace std;
#define M 100005
#define ll long long
struct node{
	int L,R,cnt,vis;
}tree[400005];
int a[M],b[M],c[M],f[M];
void build(int p,int l,int r){
	tree[p].L=l,tree[p].R=r;
	if(l==r) return;
	int mid=tree[p].L+tree[p].R>>1;
	build(2*p,l,mid);
	build(2*p+1,mid+1,r);
}
void up(int p){
	tree[p].cnt=2e9;
	if(tree[2*p].vis) tree[p].cnt=tree[2*p].cnt;
	if(tree[2*p+1].vis) tree[p].cnt=min(tree[p].cnt,tree[2*p+1].cnt);
	tree[p].vis=(tree[2*p].vis||tree[2*p+1].vis);
}
void add(int p,int x,int a){
	if(tree[p].L==tree[p].R){
		tree[p].cnt+=a;
		if(tree[p].cnt)tree[p].vis=1;
		else tree[p].vis=0;
		return;
	}
	int mid=tree[p].L+tree[p].R>>1;
	if(x<=mid) add(2*p,x,a);
	else add(2*p+1,x,a);
	up(p);
}
int query(int p){
	if(tree[p].L==tree[p].R) return tree[p].L;
	if(tree[2*p+1].vis&&tree[2*p+1].cnt==1) return query(2*p+1);
	else if(tree[2*p].vis&&tree[2*p].cnt==1) return query(2*p);
	return -1;
}
signed main(){
	int n,k;
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[i]=a[i];
	}
	sort(b+1,b+n+1);
	int len=unique(b+1,b+n+1)-b;
	for(int i=1;i<=n;i++) c[i]=lower_bound(b+1,b+len+1,a[i])-b,f[c[i]]=a[i];
	build(1,1,100000);
	for(int i=1;i<=k;i++) add(1,c[i],1);
	for(int i=1;i<=n-k+1;i++){
		int ans=query(1);
		if(ans==-1)puts("Nothing");
		else cout<<f[ans]<<endl;
		add(1,c[i],-1);
		if(i-k<=n) add(1,c[i+k],1);
	}
	return 0;
}

并查集(待学)

倍增

  • 思想

  • 画图

分块

  • 以前学习笔记

  • 很好用

posted @ 2024-02-03 09:36  Firepaw喵喵喵  阅读(18)  评论(0)    收藏  举报