hdu5618 Jam's problem again

想用动态开点的二维线段树水一下,然而TLE了。。。有人线段树套平衡树都过了。。。可能线段树套线段树再加动态开点常数确实大。。。

留着等刷完第三章习题后再搞树套树,和cdq分治一起搞,等学完cdq分治我一定会回来用正解过这题的,今天没过的代码先留着。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

typedef long long ll;
//const int maxn=1000100;
const int INF=1e9+10;

const int N=100010;
int n;
struct Point
{
    int x,y,z;
    int id;
    int ans;
    friend bool operator<(Point A,Point B)
    {
        return A.z<B.z;
    }
};Point p[N];
struct Node
{
    int l,r;
    int lz,rz;
    int cnt;
    int lx,rx;
    int ly,ry;
};Node tr[N*8];int trn;
int s[N*8],trn2;
int rt;

bool cmp(Point A,Point B)
{
    return A.id<B.id;
}

int newnode(int l,int r,int lz,int rz)
{
    int k;
    if(trn2) k=s[trn2--];
    else k=++trn;
    tr[k]={l,r,lz,rz,0,-1,-1,-1,-1};
    return k;
}

void Init(int l,int r,int lz,int rz)
{
    trn=trn2=0;
    rt=newnode(l,r,lz,rz);
}

void Free(int &k)
{
    if(k==-1) return;
    Free(tr[k].lx);
    Free(tr[k].rx);
    Free(tr[k].ly);
    Free(tr[k].ry);
    s[++trn2]=k;
    k=-1;
}

void upy(int rt)
{
    tr[rt].cnt=0;
    if(~tr[rt].ly){
        tr[rt].cnt+=tr[tr[rt].ly].cnt;
        if(tr[tr[rt].ly].cnt==0) Free(tr[rt].ly);
    }
    if(~tr[rt].ry){
        tr[rt].cnt+=tr[tr[rt].ry].cnt;
        if(tr[tr[rt].ry].cnt==0) Free(tr[rt].ry);
    }
}

void updatey(int p,int c,int rt)
{
    int l=tr[rt].l,r=tr[rt].r;
    int lz=tr[rt].lz,rz=tr[rt].rz;
    if(lz==rz){
        tr[rt].cnt++;
        return;
    }
    int m=(lz+rz)>>1;
    if(p<=m){
        if(tr[rt].ly==-1) tr[rt].ly=newnode(l,r,lz,m);
        updatey(p,c,tr[rt].ly);
    }
    else{
        if(tr[rt].ry==-1) tr[rt].ry=newnode(l,r,m+1,rz);
        updatey(p,c,tr[rt].ry);
    }
    upy(rt);
}

int queryy(int L,int R,int &rt)
{
    if(tr[rt].cnt==0&&rt!=1){
        Free(rt);
        return 0;
    }
    int l=tr[rt].l,r=tr[rt].r;
    int lz=tr[rt].lz,rz=tr[rt].rz;
    if(L<=lz&&rz<=R) return tr[rt].cnt;
    int m=(lz+rz)>>1;
    int res=0;
    if(L<=m){
        if(~tr[rt].ly) res+=queryy(L,R,tr[rt].ly);
    }
    if(R>m){
        if(~tr[rt].ry) res+=queryy(L,R,tr[rt].ry);
    }
    return res;
}

void updatex(int x,int y,int c,int rt)
{
    //cout<<"x="<<x<<" y="<<y<<" c="<<c<<" rt="<<rt<<endl;
    int l=tr[rt].l,r=tr[rt].r;
    int lz=tr[rt].lz,rz=tr[rt].rz;
    //cout<<"x="<<x<<" y="<<y<<" c="<<c<<" l="<<l<<" r="<<r<<" lz="<<lz<<" rz="<<rz<<endl;
    updatey(y,c,rt);
    if(l==r) return;
    int m=(l+r)>>1;
    if(x<=m){
        if(tr[rt].lx==-1) tr[rt].lx=newnode(l,m,lz,rz);
        updatex(x,y,c,tr[rt].lx);
    }
    else{
        if(tr[rt].rx==-1) tr[rt].rx=newnode(m+1,r,lz,rz);
        updatex(x,y,c,tr[rt].rx);
    }
}

int queryx(int xL,int xR,int yL,int yR,int &rt)
{
    if(tr[rt].cnt==0&&rt!=1){
        Free(rt);
        return 0;
    }
    int l=tr[rt].l,r=tr[rt].r;
    int lz=tr[rt].lz,rz=tr[rt].rz;
    //cout<<"xL="<<xL<<" xR="<<xR<<" yL="<<yL<<" yR="<<yR<<" l="<<l<<" r="<<r<<" lz="<<lz<<" rz="<<rz<<endl;
    if(xL<=l&&r<=xR) return queryy(yL,yR,rt);
    int m=(l+r)>>1;
    int res=0;
    if(xL<=m){
        if(~tr[rt].lx) return res+=queryx(xL,xR,yL,yR,tr[rt].lx);
    }
    if(xR>m){
        if(~tr[rt].rx) return res+=queryx(xL,xR,yL,yR,tr[rt].rx);
    }
    return res;
}

int main()
{
    freopen("in.txt","r",stdin);
    int T;cin>>T;
    while(T--){
        scanf("%d",&n);
        REP(i,1,n) scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z),p[i].id=i;
        sort(p+1,p+n+1);
        Init(1,N,1,N);
        REP(i,1,n){
            //cout<<p[i].x<<" "<<p[i].y<<" "<<p[i].z<<endl;
            p[i].ans=queryx(1,p[i].x,1,p[i].y,rt);
            updatex(p[i].x,p[i].y,1,rt);
            //cout<<p[i].ans<<endl;
        }
        for(int i=n-1;i>=1;i--) if(p[i].x==p[i+1].x&&p[i].y==p[i+1].y&&p[i].z==p[i+1].z) p[i].ans=p[i+1].ans;
        sort(p+1,p+n+1,cmp);
        REP(i,1,n) printf("%d\n",p[i].ans);
    }
    return 0;
}
View Code

 -------------------------更新----

昨天学了看了下树套树的概念,这次尝试着写一下。。。

树状数组套平衡树,WA了。。。。并不知道挂在哪。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

const int maxn=1000100;
const int INF=1e9+10;

const int N=100010;
int n;
struct Point
{
    int x,y,z;
    int id,ans;
    void read(int ID)
    {
        scanf("%d%d%d",&x,&y,&z);
        id=ID;ans=0;
    }
    friend bool operator<(Point A,Point B)
    {
        return A.z<B.z;
    }
    void debug()
    {
        printf("x=%2d y=%2d z=%2d\n",x,y,z);
    }
};Point p[maxn];

bool cmp(Point A,Point B)
{
    return A.id<B.id;
}

///-----treap
struct Node
{
    Node* ch[2];
    int r,v;
    int sz;
    Node()
    {
        ch[0]=ch[1]=NULL;
        r=rand();v=0;
        sz=1;
    }
    void up()
    {
        sz=1;
        if(ch[0]!=NULL) sz+=ch[0]->sz;
        if(ch[1]!=NULL) sz+=ch[1]->sz;
    }
};Node* rt[maxn];

void rot(Node* &o,int d)
{
    Node* k=o->ch[d^1];
    o->ch[d^1]=k->ch[d];
    k->ch[d]=o;
    o->up();k->up();
    o=k;
}

void Insert(Node* &o,int x)
{
    if(o==NULL){
        o=new Node();
        o->v=x;
        return;
    }
    int d=x<o->v?0:1;
    Insert(o->ch[d],x);
    if(o->ch[d]->r>o->r) rot(o,d^1);
    o->up();
}

int getcnt(Node* &o,int y)
{
    if(o==NULL) return 0;
    if(y<o->v) return getcnt(o->ch[0],y);
    int ls=0;
    if(o->ch[0]!=NULL) ls=o->ch[0]->sz;
    return ls+1+getcnt(o->ch[1],y);
}

///-----BIT
int lowbit(int x)
{
    return x&-x;
}

void add(int p,int y)
{
    while(p<=N){
        Insert(rt[p],y);
        p+=lowbit(p);
    }
}

int sum(int p,int y)
{
    int res=0;
    while(p){
        res+=getcnt(rt[p],y);
        p-=lowbit(p);
    }
    return res;
}

void Free(Node* &k)
{
    if(k==NULL) return;
    Free(k->ch[0]);
    Free(k->ch[1]);
    delete k;
    k=NULL;
}

void Init()
{
    REP(i,0,maxn-1) Free(rt[i]);
}

int main()
{
    freopen("in.txt","r",stdin);
    int T;cin>>T;
    while(T--){
        scanf("%d",&n);
        REP(i,1,n) p[i].read(i);
        sort(p+1,p+n+1);
        Init();
        REP(i,1,n){
            p[i].ans=sum(p[i].x,p[i].y);
            add(p[i].x,p[i].y);
        }
        for(int i=n-1;i>=1;i--) if(p[i].x==p[i+1].x&&p[i].y==p[i+1].y&&p[i].z==p[i+1].z) p[i].ans=p[i+1].ans;
        sort(p+1,p+n+1,cmp);
        REP(i,1,n) printf("%d\n",p[i].ans);
    }
    return 0;
}
View Code

改用线段树套平衡树,TLE了。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#define lson l,m,o<<1
#define rson m+1,r,o<<1|1
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))

using namespace std;

const int maxn=1000100;
const int INF=1e9+10;

const int N=100010;
int n;
struct Point
{
    int x,y,z;
    int id,ans;
    void read(int ID)
    {
        scanf("%d%d%d",&x,&y,&z);
        id=ID;ans=0;
    }
    friend bool operator<(Point A,Point B)
    {
        return A.z<B.z;
    }
    void debug()
    {
        printf("x=%2d y=%2d z=%2d\n",x,y,z);
    }
};Point p[N];

bool cmp(Point A,Point B)
{
    return A.id<B.id;
}

///-----treap
struct Node
{
    Node* ch[2];
    int r,v;
    int sz;
    Node()
    {
        ch[0]=ch[1]=NULL;
        r=rand();v=0;
        sz=1;
    }
    void up()
    {
        sz=1;
        if(ch[0]!=NULL) sz+=ch[0]->sz;
        if(ch[1]!=NULL) sz+=ch[1]->sz;
    }
};Node* rt[N<<2];

void rot(Node* &o,int d)
{
    Node* k=o->ch[d^1];
    o->ch[d^1]=k->ch[d];
    k->ch[d]=o;
    o->up();k->up();
    o=k;
}

void Insert(Node* &o,int x)
{
    if(o==NULL){
        o=new Node();
        o->v=x;
        return;
    }
    int d=x<o->v?0:1;
    Insert(o->ch[d],x);
    if(o->ch[d]->r>o->r) rot(o,d^1);
    o->up();
}

int getcnt(Node* &o,int y)
{
    if(o==NULL) return 0;
    if(y<o->v) return getcnt(o->ch[0],y);
    int ls=0;
    if(o->ch[0]!=NULL) ls=o->ch[0]->sz;
    return ls+1+getcnt(o->ch[1],y);
}

///-----Segment Tree
void update(int p,int y,int l,int r,int o)
{
    Insert(rt[o],y);
    if(l==r) return;
    int m=(l+r)>>1;
    if(p<=m) update(p,y,lson);
    else update(p,y,rson);
}

int query(int L,int R,int y,int l,int r,int o)
{
    if(L<=l&&r<=R) return getcnt(rt[o],y);
    int m=(l+r)>>1;
    int res=0;
    if(L<=m) res+=query(L,R,y,lson);
    if(R>m) res+=query(L,R,y,rson);
    return res;
}

void Free(Node* &k)
{
    if(k==NULL) return;
    Free(k->ch[0]);
    Free(k->ch[1]);
    delete k;
    k=NULL;
}

void Init()
{
    REP(i,0,(N<<2)-1) Free(rt[i]);
}

int main()
{
    freopen("in.txt","r",stdin);
    int T;cin>>T;
    while(T--){
        scanf("%d",&n);
        REP(i,1,n) p[i].read(i);
        sort(p+1,p+n+1);
        Init();
        REP(i,1,n){
            p[i].ans=query(1,p[i].x,p[i].y,1,N,1);
            update(p[i].x,p[i].y,1,N,1);
        }
        for(int i=n-1;i>=1;i--) if(p[i].x==p[i+1].x&&p[i].y==p[i+1].y&&p[i].z==p[i+1].z) p[i].ans=p[i+1].ans;
        sort(p+1,p+n+1,cmp);
        REP(i,1,n) printf("%d\n",p[i].ans);
    }
    return 0;
}
View Code

马上要打训练赛了,有时间再弄这题。。。指针太难调试,而且常数大。。。一定要把treap改成静态版的。。。

你可能感兴趣的:(hdu5618 Jam's problem again)