ZOJ 3635 树状数组+二分

这题那时怎么想就是想不出来……而且今晚没有多大状态,自己都晕了……一题没做出来……

baoge解释好久才懂……唉……线段树,树状数组用得还是不够熟啊……

WA了二发,才知道二分错了,二分好久不用,老是出错了现在……

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#define sca(a) scanf("%d",&a)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
int c[50005],a[50005],b,n;
void update(int x,int num)
{
    for(int i=x; i<=n; i+=i&(-i))
        c[i]+=num;
}
int sum(int x)
{
    int ans=0;
    for(int i=x; i>=1; i-=i&(-i))
        ans+=c[i];
    return ans;
}
int main()
{
    int i,j,m;
    while(~sca(n))
    {
        mem(c,0);
        for(i=1; i<=n; i++)
            update(i,1);
        for(i=1; i<=n; i++)
        {
            sca(m);
            int l=1,r=n;
            while(l<=r)
            {
                int mid=(l+r)/2,s=sum(mid);
                if(s>=m) r=mid-1;
                else l=mid+1;
            }
            a[i]=l;
            update(l,-1);
        }
        sca(m);
        for(i=0; i<m-1; i++)
        {
            sca(b);
            printf("%d ",a[b]);
        }
        sca(b);
        printf("%d\n",a[b]);
    }
    return 0;
}

ZOJ 3635 树状数组+二分,布布扣,bubuko.com

时间: 2024-12-25 06:37:39

ZOJ 3635 树状数组+二分的相关文章

HDU 2852 KiKi&#39;s K-Number (树状数组 &amp;&amp; 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作.这里对于一个容器提供三种操作, 分别是插入.删除和查找.输入0  e表示插入e.输入1  e表示删除e,若元素不存在输出No Elment!.输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find! 分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有

POJ 2892 Tunnel Warfare (树状数组+二分)

题目大意: 三个操作 D pos  将pos位置摧毁,让它和周围不相连. Q pos 问和pos 相连的有多少个村庄. R 修复最近摧毁的村庄. 思路分析: 树状数组记录这个区间有多少个1. 如果  [s-e] 有e-s+1个1 的话.那么这个区间是相连的. 这样的话,我们就可以用二分的办法求出与某个位置最大相连的数量. 还有这里二分 while(l<=r) { if(满足) { ans=mid; l=mid+1; } else r=mid-1; } #include <cstdio>

HDU 5592 ZYB&#39;s Premutation(树状数组+二分)

题意:给一个排列的每个前缀区间的逆序对数,让还原 原序列. 思路:考虑逆序对的意思,对于k = f[i] - f[i -1],就表示在第i个位置前面有k个比当前位置大的数,那么也就是:除了i后面的数字之外,它是在剩下的数字当中第k+1大的. 知道这个之后,可以用树状数组来帮助找出剩下的数中第k大的数,刚开始我们可以让1-n中每个元素都标记为1,那么他们的前缀和就代表它是第几小.所以,我们可以对于他们的和来二分快速寻找第k大数.其实在树状数组里面是按照第(i-k)小来找的.找完之后要删除这个元素的

POJ 2828 Buy Tickets (线段树 or 树状数组+二分)

题目链接:http://poj.org/problem?id=2828 题意就是给你n个人,然后每个人按顺序插队,问你最终的顺序是怎么样的. 反过来做就很容易了,从最后一个人开始推,最后一个人位置很容易就确定了,那最后第二个人的位置也可以推(与最后一个人的位置无关)...依次就都可以确定所有的人了. 用前缀和的思想,要是这个人的位置确定了,那么就标记这个人位置的值为0,然后回溯更新,跟求逆序对个数的思想比较类似. 线段树: 1 #include <iostream> 2 #include &l

HDU 2852 KiKi&#39;s K-Number【 树状数组 二分 】

题意:给出m个操作,0:是增加一个数,add(x,1)1:是删除一个指定的数,这个是看sum(x) - sum(x-1)是否为0,为0的话则不存在,不为0的话,则add(x,-1)2:是查询比x大的数中第k大的数,先求出比x小的个数s,假设比x大的数中第k大的数为y,那么比y小的个数有s+k个二分y的值来找 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include <cmath&g

HDU 2852 KiKi&#39;s K-Number(树状数组+二分)

KiKi's K-Number Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 2598    Accepted Submission(s): 1199 Problem Description For the k-th number, we all should be very familiar with it. Of course,t

HDU2852 KiKi&#39;s K-Number 树状数组+二分

这题就是给了你三种操作, 1:往容器中一个元素 x 2::把容器中的元素x删除 3:查询比 x大的第k个数 想法:添加元素跟删除元素  直接是以数本身为序号然后以 value值为1和-1即可,相当于计数,至于找比x第k个大的数,那就看看当前往后数k个数的第一个数是哪个就可以了,一开始直接找出来,然后往后暴力的扫了一遍,结果错了,没关系,反应很快,直接改了个二分查找,然后就过了,弄清楚如何建立这个树状数组即可 #include<iostream> #include<cstdio> #

TOJ 4602:高桥和低桥(二分或树状数组+二分)

描述 有个脑筋急转弯是这样的:有距离很近的一高一低两座桥,两次洪水之后高桥被淹了两次,低桥却只被淹了一次,为什么?答案是:因为低桥太低了,第一次洪水退去之后水位依然在低桥之上,所以不算"淹了两次".举例说明:假定高桥和低桥的高度分别是5和2,初始水位为1第一次洪水:水位提高到6(两个桥都被淹),退到2(高桥不再被淹,但低桥仍然被淹)第二次洪水:水位提高到8(高桥又被淹了),退到3.没错,文字游戏.关键在于"又"的含义.如果某次洪水退去之后一座桥仍然被淹(即水位不小于

ZOJ - 3635 Cinema in Akiba(树状数组+二分)

题意:已知有n个人,从第一个人开始每个人被安排在第ai个空座上,有m组询问,问某人所坐的位置. 分析: 1.用树状数组维护空座的个数,方法: 将所有的空座初始化为1,sum(x)则表示从座位1到座位x空座的个数. 2.对于每个人,根据sum(mid),二分找使sum(mid)大于等于a[i]的最小的mid,即第ai个空座的位置,并将该位置加上-1,则该位置的值变为0,从而不参与空座数的统计. 3.vis[q]即为标号为q的人所坐的位置. #include<cstdio> #include<