这道题 可以用很多方法做像划分树之类滴~~~
用splay虽然比划分树慢了一点,不过也只是慢了一点呀,想想有通用的解法,何必用不太常用的划分树喃~~
#include<stdio.h>
#include<string.h>
#include <cmath>
#include<algorithm>
#define fr(i,s,n) for(int i=s;i<n;++i)
#define _fr(i,n,s) for(int i=n-1;i>=s;--i)
#define fi freopen("in.txt","r",stdin)
#define cl(a) memset(a,0,sizeof(a))
using namespace std;
typedef long long ll;
const int N=1000010;
int nxt[N],data[N]; // 内存池
int l[N],r[N],siz[N],fa[N]; //siz以i为根的树中的孩子数目
int n,m;
//这里的root 都是指的当前的根
class Spt{
public:
Spt(){
fr(i,0,N) nxt[i]=i+1;
}
void zig(int &pos);
void zag(int &pos);
void splay(int &pos,int &root);
int join(int &s1,int &s2);
void split(int x,int &root,int &s1,int &s2);
void remove(int x,int &root);
int bst_find(int x,int root);
int spt_find(int x,int &root);
int bst_insert(int x,int &root);
void spt_insert(int x,int &root);
int bst_find_kth(int k,int root);
int spt_find_kth(int k,int &root);
int findmx(int &pos);
int findmn(int &pos);
void init();
int newnode(int x);
void delnode(int pos);
void disp(int root);
};
struct interval{
int l,r,k,pos;
bool operator < (const interval &x){
if ( r == x.r) return l<x.l;
return r<x.r;
}
}inter[50010];
int num[N];
int ans[50010];
int main(){
n=10;
Spt spt;
int ROOT=0;
scanf("%d%d",&n,&m);
fr(i,1,n+1){
scanf("%d",&num[i]);
}
fr(i,0,m) {scanf("%d %d %d",&inter[i].l,&inter[i].r,&inter[i].k);inter[i].pos=i;}
sort(inter,inter+m);
fr(i,inter[0].l,inter[0].r+1){
spt.spt_insert( num[i] ,ROOT);
}
//spt.disp(ROOT);
ans[inter[0].pos] = spt.spt_find_kth(inter[0].k,ROOT);
int l=inter[0].l,r=inter[0].r;
fr(i,1,m){
if ( inter[i].l > l) {
fr(ii,l,inter[i].l) spt.remove(num[ii],ROOT);
}else{
fr(ii,inter[i].l,l) spt.spt_insert(num[ii] ,ROOT);
//spt.disp(ROOT);
}
if (inter[i].r > r){
fr(ii,r+1,inter[i].r+1){
spt.bst_insert(num[ii],ROOT);
// spt.disp(ROOT);
}
}else{
fr(ii,inter[i].r+1,r+1) spt.remove(num[ii],ROOT);
}
l=inter[i].l;
r=inter[i].r;
ans[inter[i].pos] = spt.spt_find_kth(inter[i].k,ROOT);
}
fr(i,0,m){
printf("%d\n",ans[i]);
}
return 0;
}
void Spt::zig(int &pos){
int p = fa[pos];
l[p] = r[pos];
if (r[pos]) fa[ r[pos] ]=p;
r[pos] = p;
fa[ pos ] = fa[p];
fa[p] = pos;
siz[pos] = siz[p];
siz[p] = siz[ l[p] ] + siz[r[p]] +1;
if (data[fa[pos]] > data[pos]) l[fa[pos]] = pos;
else r[ fa[pos] ] = pos;
}
void Spt::zag(int &pos){
int p = fa[pos];
r[p] = l[pos];
if (l[pos]) fa[ l[pos] ] = p;
l[pos] = p;
fa[pos] = fa[p];
fa[p] = pos;
siz[pos] = siz[p];
siz[p] = siz[ l[p] ] + siz[r[p]] +1;
if (data[fa[pos]] > data[pos]) l[fa[pos]] = pos;
else r[ fa[pos] ] = pos;
}
void Spt::splay( int &pos,int &root ){
int p;
while( fa[pos] ){
p = fa[pos];
if ( !fa[p] ){
if (pos == l[p]) zig(pos);
else if( pos == r[p] ) zag(pos);
}
else{
int g = fa[p];
if (l[p] == pos && l[g] == p){
zig(p);zig(pos);
}
else if (l[g] == p && r[p] == pos ){
zag(pos);zig(pos);
}
else if (r[g] == p && l[p] == pos){
zig(pos);zag(pos);
}
else if (r[g] == p && r[p] == pos){
zag(p);zag(pos);
}
}
}
root = pos;
}
void Spt::init(){
fr(i,0,n) nxt[i]=i+1;
}
int Spt::newnode( int x ){
int p = nxt[0];
nxt[0] = nxt[p];
data[p] = x;
siz[p]=1;
return p;
}
void Spt::delnode(int pos){
l[pos] = r[pos] = fa[pos] =0;
nxt[pos] = nxt[0];
nxt[0] = pos;
siz[pos]=0;
}
int Spt::bst_insert( int x,int &root ){
if(!root){ root = newnode(x); return root;}
else if ( x < data[root] ){
int q = bst_insert( x , l[root]);
++siz[root];
fa[ l[root] ]= root;
return q;
}else{
++siz[root];
int q = bst_insert( x , r[root]);
fa[ r[root] ]= root;
return q;
}
}
void Spt::spt_insert(int x,int &root){
int q = bst_insert(x,root);
splay(q,root);
}
int Spt::bst_find(int x,int root){
if ( !root) return 0;
if (x == data[root] ) return root;
else if (x < data[root]) return bst_find(x,l[root]);
else return bst_find(x,r[root]);
}
int Spt::spt_find(int x,int &root){
int q = bst_find(x,root);
if ( q ) splay(q,root);
return q;
}
int Spt::findmx( int &root ){
int p = root;
while ( r[p] ) p = r[p];
splay(p,root);
return p;
}
int Spt::join(int &s1,int &s2){
fa[s1] = fa[s2] = 0;
if (!s1) return s2;
if (!s2) return s1;
int q = findmx(s1); //findmx以后 是就变成了树根
siz[s1] += siz[s2];
r[s1] = s2;
fa[s2] = s1;
return s1;
}
void Spt::split(int x,int &root,int &s1,int &s2){
int p = spt_find(x,root);
s1 = l[p];
s2 = r[p];
}
void Spt::remove(int x ,int &root){
int q = spt_find(x,root); //因为是spt_find找到后就已经在顶部了
if (q) {
int tmp = root;
root = join(l[root],r[root]);
delnode(tmp);
}
}
void Spt::disp(int root){
if (!root) return ;
disp(l[root]);
printf("%d\n",data[root]);
disp(r[root]);
}
int Spt::bst_find_kth( int k,int root){
if (k <= siz[l[root]]) return bst_find_kth(k,l[root]);
else {
k-=siz[l[root]];
if (k==1){
return root;
}
return bst_find_kth(k-1,r[root]);
}
}
int Spt::spt_find_kth(int k,int &root){
int p = bst_find_kth(k,root);
splay(p,root);
return data[p];
}