树状数组_二分_POJ-2182

题目链接:http://poj.org/problem?id=2182

这题似乎可以有多解,但题目里似乎没有specialjudge

本题解法较为简单,注意到每次可以确定队尾的元素,在剩下的未确定的元素中排第几。

至于值为多少就可以用二分和树状数组来解决。

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 #define lowbit(a) ((a)&(-a))
 7 #define max(a, b) ((a)>(b)?(a):(b))
 8 #define min(a, b) ((a)<(b)?(a):(b))
 9 #define MAXN 10010
10 #define PI 3.1415926
11 #define E 2.718281828
12 #define INF 0x777777f
13 typedef long long LL;
14
15 struct BIT{
16     #define bMAXN 10010
17     int bCnt, sum[bMAXN];
18     void add(int p, int v){
19         for ( ; p <= bCnt; p += lowbit(p))
20             sum[p] += v;
21     }
22     int query(int p){
23         int ret = 0;
24         for ( ; p; p -= lowbit(p))
25             ret += sum[p];
26         return ret;
27     }
28 } t;
29 int n, a[MAXN], ans[MAXN];
30
31 int find(int v){
32     int l = 1, r = n, mid;
33     while (l <= r){
34         mid = (l+r)>>1;
35         int tmp = t.query(mid);
36         if (tmp < v) l = mid+1;
37         if (tmp >= v) r = mid-1;    //每次找到最左边的那个,防止访问已被删除的节点
38     } return l;
39 }
40 int main(){
41     scanf("%d", &n); t.bCnt = n;
42     for (int i = 2; i <= n; i++) scanf("%d", &a[i]);
43     for (int i = 1; i <= n; i++) t.add(i, 1);    //初始化
44     for (int i = n; i >= 1; i--){
45         ans[i] = find(a[i]+1);
46         t.add(ans[i], -1);
47     }
48     for (int i = 1; i <= n; i++) printf("%d\n", ans[i]);
49     return 0;
50 }
时间: 2024-08-02 01:38:34

树状数组_二分_POJ-2182的相关文章

多校第十场:HDU 4973 树状数组+前缀+二分

思路:比赛的时候看到这题感觉是线段树或者树状数组,但是因为要区间加倍,然后不知所措了,想了好久也不知道怎么把那个加倍的数怎么处理,然后就一直想第一道题了就没管这题了.虽然之前也做过这种类型的树状数组,不过这题确实是比较机智,把树状数组用得是非常爽. sum[i]是树状数组的前缀和,cnt[i]表示第i个数共有多少个数. 更新加倍过程:我们让(l,r)这个区间加倍的时候,二分树状数组找到l所对应的数,找到r对应的数,单点更新这两个数,为什么要单点更新这两个数呢?因为比如:1 1 1 2 2 2 3

USACO5.3 IDDFS_强连通_二维树状数组_斐蜀定理_矩形切割

启发式搜索 启发式搜索的主要思想是通过评价一个状态有"多好"来改进对于解的搜索. 方法#1:启发式剪枝 估价函数最简单最普通的用法是进行剪枝.假设有一个求最小代价的一个搜索,使用一个可行的估价函数.如果搜到当前状态时代价为A,这个状态的估价函数是B,那么从这个状态开始搜所能得到的最小代价是A+B.如果当前最优解是C满足C 方法#2:最佳优先搜索 最佳搜索可以看成贪心的深度优先搜索. 与一般搜索随意扩展后继节点不同,最优优先搜索按照估价函数所给的他们的"好坏"的顺序扩

[bzoj3529][Sdoi2014]数表_树状数组_莫比乌斯反演

数表 bzoj-3529 Sdoi-2014 题目大意:n*m的数表,第i行第j列的数是同时整除i和j的所有自然数之和.给定a,求数表中所有不超过a的和. 注释:$1\le n,m \le 10^5$. 想法:我们先不考虑那个a的限制:我们设f(i)表示整除i的自然数之和. $\sum\limits_{i=1}^n\sum\limits_{j=1}^m f(gcd(i,j))$ $\sum\limits_{i=1}^n\sum\limits_{j=1}^m f(d)\cdot [gcd(i,j)

POJ2182 Lost Cows 树状数组,二分

题意:给n个奶头身高从1到n,现在奶牛排成一列,给n-1个数字,为第二号奶牛到第n号奶牛前面比它矮的奶牛个数. 求这个序列每个奶牛的身高. 思路:从最后一个奶牛开始判断,因为最后一个奶牛是和前面所有奶牛做比较的,我们可以根据比它矮的奶牛个数确定它的身高,如果前面有3个比它矮那么它身高绝对为4,而继续判断前一个奶头身高时,要把这个奶牛剔除考虑, 所以我们想到可以维护一个长度为n的01序列,为1表示奶牛还在,奶牛从后往前遍历,设比它矮的有k个,每次找奶牛身高,就是找存在的奶牛中k+1的位置,也就是前

HDU 5196 DZY Loves Inversions(树状数组,二分)

这题之前CC做过类似的,思路如官方题解. 代码: #include <stdio.h> #include <string.h> #include <algorithm> using namespace std; const int N = 100005; typedef long long ll; int n, m; ll q; struct Hash { int v, id; void read(int id) { scanf("%d", &

树状数组_一维

// 模板水题 敌兵布阵 HDU - 1166 class TreeArray{ public: const static int cmaxn = 1e5; /// Todo: 修改区间的最大值 int cdate[cmaxn]; int max_sz; // 表示元素的个数 在init初始化 void init(int size) { memset(cdate, 0, sizeof(cdate)); max_sz = size; // 初始化本次样例的元素的个数 } void init(int

树状数组_二维

class TreeArraryTwo{ public : const static int cmaxn = 1e3+200; int date[cmaxn][cmaxn]; int xsz, ysz; void init(int size_x, int size_y) { xsz = size_x; ysz = size_y; memset(date, 0, sizeof(date)); } inline int lowbit(int idx) { return idx & -idx; } v

[BZOJ 4418][Shoi2013]扇形面积并(树状数组+二分)

Description 给定N个同心的扇形,求有多少面积,被至少K个扇形所覆盖. Solution 打开发现是计算几何还以为是看错题号了QwQ 其实就是遇到一条开始的边+1,遇到一条结束的边-1,a1>a2的话就再加上一个完整的圆 计算每一部分只需要找到第cnt-k+1大的半径,在树状数组上二分就好了 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #inc

HDU3727 Jewel(主席树+树状数组(或二分))

Problem Description Jimmy wants to make a special necklace for his girlfriend. He bought many beads with various sizes, and no two beads are with the same size. Jimmy can't remember all the details about the beads, for the necklace is so long. So he