码迷,mamicode.com
首页 > 其他好文 > 详细

HDU HDOJ5412(树套树

时间:2015-11-07 06:09:29      阅读:323      评论:0      收藏:0      [点我收藏+]

标签:

题目:要求支持带修改维护区间第k大的值。所谓的动态区间第k大。

思路:题解说的是树状数组套treap,然而没想通树状数组怎么维护。。。线段树的话就是把所有的值离散化一下,离线建个关于值的线段树,每个节点是一个treap,treap里的值用位置做关键字,然后做区间查询,复杂度是O(nlogn*logn)。基本也是经典的树套树做法。。。。然后赛后写了两遍都没过。。。。。今天心血来潮再挑战一下,结果从8点调到晚上1点。其间各种爆内存各种re各种t。。。。。随机数据对拍了好久没拍出问题来。。。。然后一直t,,后来突然想到改交vc,结果wa了。。。。然后搞了个数据,结果本地直接re。。简直凌乱了。。。然后随便试试把数组开大。。。结果就过了。。我草。。。明明g++开4e6都爆内存,vc开5e6居然还有富余。。。。然后再开个栈外挂,速度直逼标程。。。。

结论:这题有毒。。。。基本都是整体二分过的。。。有时间学习一下。。免得这么但疼。。。

技术分享
/*
* @author:  Cwind
* http://www.cnblogs.com/Cw-trip/
*/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <map>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <vector>
#include <queue>
#include <stack>
#include <functional>
#include <set>
#include <cmath>
using namespace std;
#define IOS std::ios::sync_with_stdio(false);std::cin.tie(0)
#define pb push_back
#define PB pop_back
#define fs first
#define se second
#define sq(x) (x)*(x)
#define eps 0.00000001
#define IINF (1<<29)
#define LINF (1ll<<59)
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> P;
const int maxNode=5e6+300;
struct treapNode{
    treapNode *ch[2];
    int right,val;
    int sz;
    treapNode():sz(0){}
    int cmp(int x) const {
        if(x==val) return -1;
        return x>val;
    }
    void maintain(){
        sz=ch[0]->sz+ch[1]->sz+1;
    }
}pool[maxNode];
int ph=0;
treapNode *null=new treapNode();
treapNode *newtreapNode(int v){
    treapNode *n=&pool[ph++];
    n->val=v;
    n->right=rand();
    n->ch[0]=n->ch[1]=null;
    return n;
}
void rotate(treapNode *&o,int d){
    treapNode *k=o->ch[d^1];
    o->ch[d^1]=k->ch[d];
    k->ch[d]=o;
    o->maintain();
    k->maintain();
    o=k;
}
void insert(treapNode *&o,int x){
    if(o==null) o=newtreapNode(x);
    else{
        int d=o->val<x;
        insert(o->ch[d],x);
        if(o->ch[d]->right>o->right) rotate(o,d^1);
    }
    o->maintain();
}
void remove(treapNode *&o,int x){
    int d=o->cmp(x);
    if(d==-1){
        if(o->ch[0]==null) o=o->ch[1];
        else if(o->ch[1]==null) o=o->ch[0];
        else{
            int d2=o->ch[0]->right>o->ch[1]->right;
            rotate(o,d2);
            remove(o->ch[d2],x);
        }
    }else remove(o->ch[d],x);
    if(o!=null) o->maintain();
}
int findless(treapNode *o,int x){
    int r=0;
    while(o!=null){
        if(o->val>x){
            o=o->ch[0];
        }
        else{
            r+=o->ch[0]->sz+1;
            o=o->ch[1];
        }
    }
    return r;
}
int culbetween(treapNode *o,int l,int r){
    return findless(o,r)-findless(o,l-1);
}
int ah;
const int maxn=1e6+3000;
struct QU{
    int t,a,b,c;
}qu[maxn];
struct segNode{
    int l,r;
    treapNode *root;
    segNode *ch[2];
}segpool[maxNode];
int segh=0;
segNode *newsegNode(){
    segNode *n=&segpool[segh++];
    n->root=null;
    return n;
}
void buildSeg(segNode *n,int l,int r){
    n->l=l,n->r=r;
    if(r-l<=1) return;
    n->ch[0]=newsegNode();
    n->ch[1]=newsegNode();
    buildSeg(n->ch[0],l,(l+r)/2);
    buildSeg(n->ch[1],(r+l)/2,r);
}
void segInsert(segNode *n,int x,int p){
    int r=n->r,l=n->l;
    int mid=(r+l)/2;
    treapNode *&tn=n->root;
    insert(tn,p);
    if(r-l<=1) return;
    if(x>=mid)
        segInsert(n->ch[1],x,p);
    else
        segInsert(n->ch[0],x,p);
}
void segRemove(segNode *n,int x,int p){
    int r=n->r,l=n->l;
    int mid=(r+l)/2;
    treapNode *&tn=n->root;
    remove(tn,p);
    if(r-l<=1) return;
    if(x>=mid)
        segRemove(n->ch[1],x,p);
    else
        segRemove(n->ch[0],x,p);
}
int segQuery(segNode *n,int a,int b,int k){
    treapNode *tn=n->root;
    segNode *chl=n->ch[0],*chr=n->ch[1];
    int l=n->l,r=n->r;
    if(r-l<=1) return l;
    int q1=culbetween(chl->root,a,b);
    if(q1>=k) return segQuery(chl,a,b,k);
    else return segQuery(chr,a,b,k-q1);
}
int N;
int deca[maxn];
int idx(int x){
    return lower_bound(deca,deca+ah,x)-deca;
}
segNode *segRoot;
void clear(){
    ph=0;
    segh=0;
    segRoot=newsegNode();
}
int a[maxn];

template <class T>
inline bool scan_d(T &ret) {
    char c;
    int sgn;
    if(c=getchar(),c==EOF) return 0; //EOF
    while(c!=-&&(c<0||c>9)) c=getchar();
    sgn=(c==-)?-1:1;
    ret=(c==-)?0:(c-0);
    while(c=getchar(),c>=0&&c<=9) ret=ret*10+(c-0);
    ret*=sgn;
    return 1;
}
inline void out(int x) {
    if(x>9) out(x/10);
    putchar(x%10+0);
}

int main(){
    freopen("/home/slyfc/CppFiles/in","r",stdin);
    freopen("/home/slyfc/CppFiles/out","w",stdout);
    while(cin>>N){
        clear();
        for(int i=1;i<=N;i++){ 
            scan_d(a[i]);
            deca[i-1]=a[i];
        }
        int Q;
        scan_d(Q);
        int an=N;
        for(int i=1;i<=Q;i++){
            int t;
            scan_d(t);
            if(t==1){
                int l,v;
                scan_d(l);scan_d(v);
                qu[i].a=l,qu[i].b=v;
                deca[an++]=v;
            }
            else{
                int l,r,k;
                scan_d(l);scan_d(r);scan_d(k);
                qu[i].a=l,qu[i].b=r,qu[i].c=k;
            }
            qu[i].t=t;
        }
        sort(deca,deca+an);
        ah=unique(deca,deca+an)-deca;
        buildSeg(segRoot,0,ah);
        for(int i=1;i<=N;i++)
            segInsert(segRoot,idx(a[i]),i);
        for(int i=1;i<=Q;i++){
            if(qu[i].t==1){
                int l=qu[i].a,v=qu[i].b;
                segRemove(segRoot,idx(a[l]),l);
                a[l]=v;
                segInsert(segRoot,idx(v),l);
            }else{
                int l=qu[i].a,r=qu[i].b,k=qu[i].c;
                printf("%d\n",deca[segQuery(segRoot,l,r,k)]);
            }
        }
    }
    return 0;
}
View Code

 

HDU HDOJ5412(树套树

标签:

原文地址:http://www.cnblogs.com/Cw-trip/p/4944071.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!