您的位置:首页 > 其它

poj 2352 treap

2017-08-12 14:41 323 查看
题意:先按Y的升序然后再按X的升序给出坐标,求出每个坐标左下方有多少个点,最后输出有从0到n-1个点的坐标有多少个。

分析:本题可以看成是 树状数组的入门题,但是用treap同样也可以解决。由于坐标是按照y递增的顺序输入。所以不需要记录、处理y坐标,对x坐标维护一个treap,对每个节点维护一个总节点数sum。 虽然没有完全相同的两个点,但是x坐标可以相同,所以储存一个当前节点的个数val,最后计算的时候这是要考略的,由于忽略这个WA了三次。

简单的treap,每次插入一个x,然后查询小于等于它的节点的个数就行了。

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
using namespace std;
struct node
{
int r,v,sum,val;
node* ch[2];
node (int v):v(v){ch[0] = ch[1] = NULL; r = rand(); sum = 1; val = 1;}
bool operator <(const node &a) const
{
return r <a.r;
}
int cmp(int x)
{
if(v == x) return -1;
return x < v ? 0 : 1;
}
};
node *root;
void pushup(node* &o)
{
o->sum = o->val;
if(o->ch[0] != NULL) o->sum += o->ch[0]->sum;
if(o->ch[1] != NULL) o->sum += o->ch[1]->sum;
}
void rotate(node* &o, int d)
{
node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d];k ->ch[d] = o;
pushup(o);
pushup(k);
if(o == root) root = k;
o = k;
}
void insert(node* &o, int x)
{
if(o == NULL) o = new node(x);
else
{
int d = o->cmp(x);
if(d == -1)
{
o->val ++;
o->sum ++;
}
else
{
insert(o->ch[d],x);
pushup(o);
if(o->ch[d]->r > o->r) rotate(o,d^1);
}
}
}
int find(node* &o, int x)
{
//cout << o->v <<"    " << x << endl;
int ans = 0;
int d = o->cmp(x);
if(d == -1)
{
ans += o->val - 1;
if(o->ch[0] != NULL) ans += o->ch[0]->sum;
return ans;
}
else
{
if(d == 1) ans += o->val;
if(d == 1 && o->ch[0] != NULL) ans += o->ch[0]->sum;
return ans += find(o->ch[d],x);
}
}
int ans[15000+ 5];
int main()
{
int n;
while(~scanf("%d",&n))
{
root = NULL;
memset(ans,0,sizeof(ans));
for(int i = 1; i <= n; i++)
{
int x,y; scanf("%d %d",&x,&y);
insert(root,x);
int pos = find(root,x);
//cout << pos << endl;
ans[pos] ++;
}
for(int i = 0; i < n; i ++)
{
printf("%d\n",ans[i]);
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: