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; }
-------------------------更新----
昨天学了看了下树套树的概念,这次尝试着写一下。。。
树状数组套平衡树,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; }
改用线段树套平衡树,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; }
马上要打训练赛了,有时间再弄这题。。。指针太难调试,而且常数大。。。一定要把treap改成静态版的。。。
-------------------更新-----
把treap改成静态版的。。。由TLE变成WA了。。
#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) { if(A.z<B.z) return 1; if(A.z==B.z){ if(A.x<B.x) return 1; if(A.x==B.x) return A.y<B.y; return 0; } return 0; } 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 { int ch[2]; int r,v; int sz; Node() { ch[0]=ch[1]=-1; r=rand();v=0; sz=1; } };Node tr[N*20];int rt[maxn],tot; int newnode() { ++tot; tr[tot].ch[0]=tr[tot].ch[1]=-1; tr[tot].r=rand();tr[tot].v=0; tr[tot].sz=1; return tot; } void up(int rt) { int lc=tr[rt].ch[0],rc=tr[rt].ch[1]; tr[rt].sz=1; if(~lc) tr[rt].sz+=tr[lc].sz; if(~rc) tr[rt].sz+=tr[rc].sz; } void rot(int &o,int d) { int k=tr[o].ch[d^1]; tr[o].ch[d^1]=tr[k].ch[d]; tr[k].ch[d]=o; up(o);up(k); o=k; } void Insert(int &o,int x) { if(o==-1){ o=newnode(); tr[o].v=x; return; } int d=x<tr[o].v?0:1; Insert(tr[o].ch[d],x); if(tr[tr[o].ch[d]].r>tr[o].r) rot(o,d^1); up(o); } int getcnt(int &o,int y) { if(o==-1) return 0; if(y<tr[o].v) return getcnt(tr[o].ch[0],y); int ls=0; if(tr[o].ch[0]==-1) ls=tr[tr[o].ch[0]].sz; return ls+1+getcnt(tr[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 Init() { memset(rt,-1,sizeof(rt)); tot=0; } 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(); //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+1; 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; }
-----------------更新------
静下心来重写了一遍就过了。。。而且1A了。。。。也没去看题解数据什么的。。。。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #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=2000100; const int INF=1e9+10; const int N=100010; struct Point { int x,y,z; int id,ans; friend bool operator<(Point A,Point B) { if(A.z<B.z) return 1; if(A.z==B.z){ if(A.x<B.x) return 1; if(A.x==B.x) return A.y<B.y; return 0; } return 0; } void read(int ID) { scanf("%d%d%d",&x,&y,&z); id=ID;ans=0; } friend bool operator==(Point A,Point B) { return A.x==B.x&&A.y==B.y&&A.z==B.z; } };Point p[maxn];int n; bool cmp(Point A,Point B) { return A.id<B.id; } ///---treap struct Node { int ch[2]; int r,v; int sz; };Node tr[maxn];int tot; int rt[maxn]; void up(int o) { tr[o].sz=1; if(~tr[o].ch[0]) tr[o].sz+=tr[tr[o].ch[0]].sz; if(~tr[o].ch[1]) tr[o].sz+=tr[tr[o].ch[1]].sz; } int newnode() { ++tot; tr[tot].ch[0]=tr[tot].ch[1]=-1; tr[tot].r=rand();tr[tot].v=0; tr[tot].sz=1; return tot; } void rot(int &o,int d) { int k=tr[o].ch[d^1]; tr[o].ch[d^1]=tr[k].ch[d]; tr[k].ch[d]=o; up(o);up(k); o=k; } void Insert(int &o,int x) { if(o==-1){ o=newnode(); tr[o].v=x; return; } int d=x<tr[o].v?0:1; Insert(tr[o].ch[d],x); if(tr[tr[o].ch[d]].r>tr[o].r) rot(o,d^1); up(o); } int getcnt(int &o,int k) { if(o==-1) return 0; if(k<tr[o].v) return getcnt(tr[o].ch[0],k); int ls=tr[o].ch[0]==-1?0:tr[tr[o].ch[0]].sz; return ls+1+getcnt(tr[o].ch[1],k); } ///---BIT int lowbit(int x) { return x&-x; } int sum(int p,int y) { int res=0; while(p){ res+=getcnt(rt[p],y); p-=lowbit(p); } return res; } void add(int p,int y) { while(p<=N){ Insert(rt[p],y); p+=lowbit(p); } } void Init(int N) { memset(rt,-1,sizeof(rt)); tot=0; } 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(N); 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]==p[i+1]) 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; }
仔细看了一下上面那份WA的代码,原来是在getcnt的时候把if(tr[o].ch[0]!=-1)写成if(tr[o].ch[0]==-1)了。。。改了一下也过了。。。
#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) { if(A.z<B.z) return 1; if(A.z==B.z){ if(A.x<B.x) return 1; if(A.x==B.x) return A.y<B.y; return 0; } return 0; } 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 { int ch[2]; int r,v; int sz; };Node tr[N*20];int rt[maxn],tot; int newnode() { ++tot; tr[tot].ch[0]=tr[tot].ch[1]=-1; tr[tot].r=rand();tr[tot].v=0; tr[tot].sz=1; return tot; } void up(int rt) { int lc=tr[rt].ch[0],rc=tr[rt].ch[1]; tr[rt].sz=1; if(~lc) tr[rt].sz+=tr[lc].sz; if(~rc) tr[rt].sz+=tr[rc].sz; } void rot(int &o,int d) { int k=tr[o].ch[d^1]; tr[o].ch[d^1]=tr[k].ch[d]; tr[k].ch[d]=o; up(o);up(k); o=k; } void Insert(int &o,int x) { if(o==-1){ o=newnode(); tr[o].v=x; return; } int d=x<tr[o].v?0:1; Insert(tr[o].ch[d],x); if(tr[tr[o].ch[d]].r>tr[o].r) rot(o,d^1); up(o); } int getcnt(int &o,int y) { if(o==-1) return 0; if(y<tr[o].v) return getcnt(tr[o].ch[0],y); int ls=0; if(tr[o].ch[0]!=-1) ls=tr[tr[o].ch[0]].sz; return ls+1+getcnt(tr[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 Init() { memset(rt,-1,sizeof(rt)); tot=0; } 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; }
没有AC不了的题,只有不努力的ACMER!