您的位置:首页 > 其它

Poj 2828 Buy Tickets \ Zoj 3635 Cinema in Akiba

2013-08-01 12:51 381 查看
这两道题思路是一样的。

第一题:http://poj.org/problem?id=2828

题意:依次插入人,每个人插入的地方告知,求最终的排位。

乍看用链表来做即可,可是这样肯定会超时,不信试试:

#include <iostream>
#include <stdlib.h>
#include <stdio.h>
using namespace std;

struct People
{
int val;
People() {}
People(int _val)
{
val = _val;
next = NULL;
}
People * next;
};

int size = 0;

int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif

int n;
int pos,val;
int size = -1;
while(scanf(" %d",&n)!=EOF)
{
People * head;
People * last;
head = last = new People(-1);
size = 0;
for(int i=0; i<n; i++)
{
scanf(" %d %d",&pos,&val);
if(size <= pos)
{
last->next = new People(val);
last = last->next;
}
else
{
People * temp = head;
int count = 0;
while(temp!=NULL)
{
if(count == pos)
{
break;
}
temp = temp->next;
count++;
}
People * cur = temp->next;
temp->next = new People(val);
temp->next->next = cur;
}
size++;
}
People *temp = head->next;
if(temp!=NULL)
{

while(temp->next!=NULL)
{
printf("%d ",temp->val);
temp = temp->next;
}
printf("%d",temp->val);

}
printf("\n");
}
return 0;
}


其实我们可以这样想,题目中的数据是一次插入的。如果我们反过来思考,从后往前的话,最后一个人的位置肯定不发生变化,接下来,在最后一个人位置不发生变化的情况下,倒数第二个人的位置也不发生变化,一次类推。我们只要用线段树维护一个关于区间空位个数的数组即可。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

#define Maxn 200005
#define lx (x<<1)
#define rx ((x<<1)|1)
#define MID ((l + r)>>1)

struct People
{
int pos;
int val;
};

People p[Maxn];

//维护空位
int S[Maxn<<2];
//最后的序列
int A[Maxn];

void pushUp(int x)
{
S[x] = S[lx] + S[rx];
}
void build(int l,int r,int x)
{
if(l == r)
{
S[x] = 1;
return;
}
build(l,MID,lx);
build(MID+1,r,rx);
pushUp(x);
}
void update(int p,int d,int l,int r,int x)
{
if(l == r)
{
S[x] = 0;
A[l] = d;
return;
}
if(p<S[lx]) update(p,d,l,MID,lx);
else update(p-S[lx],d,MID+1,r,rx);
pushUp(x);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif

int n;
while(scanf(" %d",&n)!=EOF)
{
for(int i=0;i<n;i++)
{
scanf(" %d %d",&p[i].pos,&p[i].val);
}
build(0,n-1,1);
for(int i=n-1;i>=0;i--)
{
update(p[i].pos,p[i].val,0,n-1,1);
}
for(int i=0;i<n-1;i++)
{
printf("%d ",A[i]);
}
printf("%d\n",A[n-1]);
}
return 0;
}


第二题:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3635

这题是类似的,也是维护空位个数。

#include <iostream>
#include <stdlib.h>
#include <stdio.h>

using namespace std;

#define Maxn 50005
#define lx (x<<1)
#define rx ((x<<1)|1)
#define MID ((l + r)>>1)

int S[Maxn<<2];
int A[Maxn];
//排位
int rank[Maxn];

void pushUp(int x)
{
S[x] = S[lx] + S[rx];
}
void build(int l,int r,int x)
{
if(l == r)
{
S[x] = 1;
return;
}
build(l,MID,lx);
build(MID+1,r,rx);
pushUp(x);
}
void update(int p,int d,int l,int r,int x)
{
if(l == r)
{
S[x] = 0;
A[l] = d;
rank[d] = l;
return;
}
if(p<S[lx]) update(p,d,l,MID,lx);
else update(p-S[lx],d,MID+1,r,rx);
pushUp(x);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif

int n;
int p;
int q;
while(scanf(" %d",&n)!=EOF)
{
build(1,n,1);
for(int i=1;i<=n;i++)
{
scanf(" %d",&p);
p--;
update(p,i,1,n,1);
}
scanf(" %d",&q);
for(int i=1;i<=q;i++)
{
scanf(" %d",&p);
printf("%d",rank[p]);
if(i!=q) printf(" ");
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: