POJ 2182 Lost Cows 线段树 or 树状数组

来源:互联网 发布:杭州淘宝供货商怎么找 编辑:程序博客网 时间:2024/05/21 08:56

这道题还是很经典的

给出了一个序列,代表的是比该位置的牛靠前站的且序号比他小的牛的个数

然后思想类似于2828,正序看的话,看不出有什么规律,但是逆序的话,就能看出当前序列的最后一头牛的编号是可以确定的,就相当于有一个队列,初始化全为1,有牛占了就把相应位置变为0,然后我们只管那些位置为1的地方,往里一头一头的塞牛,塞一头,能塞的地方就少一个,但是和之前塞过的就没关系了,这也符合题目中,只管比该位置靠前的且序号小的  这个条件


/*ID: sdj22251PROG: inflateLANG: C++*/#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define MAXN 10000#define INF 1000000000#define eps 1e-7#define PI 3.1415926535898#define L(x) x<<1#define R(x) x<<1|1using namespace std;struct node{    int left, right, mid;    int cnt;}tree[4 * MAXN];int a[MAXN], ans[MAXN];void make_tree(int s, int e, int C){    tree[C].left = s;    tree[C].right = e;    tree[C].mid = (s + e) >> 1;    tree[C].cnt = tree[C].right - tree[C].left + 1;    if(s == e) return;    make_tree(s, tree[C].mid, L(C));    make_tree(tree[C].mid + 1, e, R(C));}void insert(int p, int x, int C){    tree[C].cnt--;    if(tree[C].left == tree[C].right)    {        ans[x] = tree[C].left;        return;    }    if(tree[L(C)].cnt > p)    insert(p, x, L(C));    else insert(p - tree[L(C)].cnt, x, R(C));}int main(){    int n;    scanf("%d", &n);    make_tree(1, n, 1);    for(int i = 2; i <= n; i++)    scanf("%d", &a[i]);    for(int i = n; i >= 1; i--)        insert(a[i], i, 1);    for(int i = 1; i <= n; i++)        printf("%d\n", ans[i]);    return 0;}

下面是树状数组做法

其实还是那个原理 ,倒序推。刚开始的时候把n个位置都准备好,然后塞牛,塞一头就把相关的位置删1,表示之前能站的地方少了一个。

然后倒序找位置的时候,用的是二分查找。因为树状数组的和,也是有序的

/*ID: sdj22251PROG: inflateLANG: C++*/#include <iostream>#include <vector>#include <list>#include <map>#include <set>#include <deque>#include <queue>#include <stack>#include <bitset>#include <algorithm>#include <functional>#include <numeric>#include <utility>#include <sstream>#include <iomanip>#include <cstdio>#include <cmath>#include <cstdlib>#include <cctype>#include <string>#include <cstring>#include <cmath>#include <ctime>#define MAXN 10000#define INF 1000000000using namespace std;int a[MAXN];int ans[MAXN];int t[MAXN], n;int lowbit(int x){    return x & -x;}void modify(int x, int v){    for(int i = x; i <= n; i += lowbit(i))        a[i] += v;}int getsum(int x){    int sum = 0;    for(int i = x; i > 0; i -= lowbit(i))        sum += a[i];    return sum;}int search(int x){    int low = 1;    int high = n;    int mid;    while(low <= high)    {        mid = (low + high) >> 1;        int tmp = getsum(mid);        if(x <= tmp) high = mid - 1;        else low = mid + 1;    }    return low;}int main(){    scanf("%d", &n);    for(int i = 1; i <= n; i++)        modify(i, 1);//把这些位置准备好,表示都可以站牛    for(int i = 2; i <= n; i++)        scanf("%d", &t[i]);    for(int i = n; i >= 1; i--)    {        ans[i] = search(t[i] + 1);         modify(ans[i], -1); //这头牛占了一个位置,把之后有关系的地方都删掉这个1    }    for(int i = 1; i <= n; i++)        printf("%d\n", ans[i]);    return 0;}