社区讨论
树套树求卡常
P2617Dynamic Rankings参与者 4已保存回复 8
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 8 条
- 当前快照
- 1 份
- 快照标识符
- @m1j5bj0z
- 此快照首次捕获于
- 2024/09/26 18:23 去年
- 此快照最后确认于
- 2025/11/04 18:45 4 个月前
CPP
#include<bits/stdc++.h>
using namespace std;
const int N=100005,INF=2147483647;
mt19937_64 rnd(time(0));
int n,m;
int input[N];
struct Node {
int l,r;
int key,val;
int size;
}tre[40*N];
#define lson tre[now].l
#define rson tre[now].r
int root[4*N],idx;
int x,y,z;
inline int gnode(int key) {
tre[++idx].key=key;
tre[idx].val=rnd();
tre[idx].size=1;
return idx;
}
inline void maintain(int now) {tre[now].size=tre[lson].size+tre[rson].size+1;}
inline void split(int now,int key,int& x,int& y) {
if(!now) x=y=0;
else {
if(tre[now].key<=key) {
x=now;
split(rson,key,rson,y);
}else {
y=now;
split(lson,key,x,lson);
}
maintain(now);
}
}
inline int merge(int x,int y) {
if(!x || !y) return x+y;
if(tre[x].val>=tre[y].val) {
tre[x].r=merge(tre[x].r,y);
maintain(x);
return x;
}else {
tre[y].l=merge(x,tre[y].l);
maintain(y);
return y;
}
}
inline void insert(int& root,int num) {
split(root,num-1,x,y);
x=merge(x,gnode(num));
root=merge(x,y);
}
inline void del(int& root,int num) {
split(root,num,x,y);
split(x,num-1,x,z);
z=merge(tre[z].l,tre[z].r);
root=merge(x,merge(z,y));
}
inline int lst(int& root,int k) {
split(root,k-1,x,y);
if(x==0) return -INF;
int now=x,ans;
while(rson) now=rson;
ans=tre[now].key;
merge(x,y);
return ans;
}
inline int nxt(int& root,int k) {
split(root,k,x,y);
if(y==0) return INF;
int now=y,ans;
while(lson) now=lson;
ans=tre[now].key;
merge(x,y);
return ans;
}
inline int grnk(int& root,int k) { // 查询值 k 的排名,k 可能不存在
split(root,k-1,x,y);
int ans=tre[x].size;
merge(x,y);
return ans;
}
// 线段树
struct Tnode {
int l,r;
}Tre[4*N];
#define mid (Tre[now].l+Tre[now].r>>1)
#define Lson (now*2)
#define Rson (now*2+1)
inline int gsiz(int now) {return Tre[now].r-Tre[now].l+1;}
inline void build(int now,int l,int r) {
Tre[now].l=l,Tre[now].r=r;
for(int i=Tre[now].l;i<=Tre[now].r;++i) insert(root[now],input[i]);
if(l==r) return;
build(Lson,l,mid);build(Rson,mid+1,r);
}
inline void change(int now,int p,int k) {
if(Tre[now].l>p || Tre[now].r<p) return;
del(root[now],input[p]);
insert(root[now],k);
if(Tre[now].l==Tre[now].r) return;
change(Lson,p,k);change(Rson,p,k);
}
inline int query_k(int now,int l,int r,int k) {
if(Tre[now].l>r || Tre[now].r<l) return 0;
if(Tre[now].l>=l && Tre[now].r<=r) return grnk(root[now],k);
return query_k(Lson,l,r,k)+query_k(Rson,l,r,k);
}
inline int query_lst(int now,int l,int r,int k) {
if(Tre[now].l>r || Tre[now].r<l) return -INF;
if(Tre[now].l>=l && Tre[now].r<=r) return lst(root[now],k);
return max(query_lst(Lson,l,r,k),query_lst(Rson,l,r,k));
}
inline int query_nxt(int now,int l,int r,int k) {
if(Tre[now].l>r || Tre[now].r<l) return INF;
if(Tre[now].l>=l && Tre[now].r<=r) return nxt(root[now],k);
return min(query_nxt(Lson,l,r,k),query_nxt(Rson,l,r,k));
}
int query_rnk(int l,int r,int k) {
int L=0,R=1e9,Mid,ans=0;
while(L<=R) {
Mid=L+R>>1;
if(query_k(1,l,r,Mid)+1<=k) L=Mid+1,ans=Mid;
else R=Mid-1;
}
return ans;
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> n >> m;
for(int i=1;i<=n;++i) cin >> input[i];
build(1,1,n);
int l,r,k,ans;char op;
for(int i=1;i<=m;++i) {
cin >> op;
if(op=='Q') {
cin >> l >> r >> k;
cout << query_rnk(l,r,k) << '\n';
}else {
cin >> l >> k;
change(1,l,k);
input[l]=k;
}
}
return 0;
}
回复
共 8 条回复,欢迎继续交流。
正在加载回复...