• [bzoj3192][JLOI2013]删除物品(树状数组)


    3192: [JLOI2013]删除物品

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 872  Solved: 508
    [Submit][Status][Discuss]

    Description

     
    箱子再分配问题需要解决如下问题:
     (1)一共有N个物品,堆成M堆。
     (2)所有物品都是一样的,但是它们有不同的优先级。
     (3)你只能够移动某堆中位于顶端的物品。
     (4)你可以把任意一堆中位于顶端的物品移动到其它某堆的顶端。若此物品是当前所有物品中优先级最高的,可以直接将之删除而不用移动。
     
    (5)求出将所有物品删除所需的最小步数。删除操作不计入步数之中。
     (6)只是一个比较难解决的问题,这里你只需要解决一个比较简单的版本:
             不会有两个物品有着相同的优先级,且M=2
     

    Input

    第一行是包含两个整数N1,N2分别表示两堆物品的个数。
    接下来有N1行整数按照从顶到底的顺序分别给出了第一堆物品中的优先级,数字越大,优先级越高。
    再接下来的N2行按照同样的格式给出了第二堆物品的优先级。
     

    Output

    对于每个数据,请输出一个整数,即最小移动步数。
     

    Sample Input

    3 3
    1
    4
    5
    2
    7
    3

    Sample Output

    6

    HINT

    1<=N1+N2<=100000

    Source

    开始水博

    接着上一个纪元讲的内容

    这道题其实模拟就好,看题解前最好手动模拟一下

    (快去模拟!)

    那么在模拟时,容易想到的优化是把两个栈的栈顶接上,直接维护数列

    维护时可以排序一遍,得出每个元素的顺序

    比如对于5 4 1 2 7 3

    排完序就是3 4 6 2 1 5

    接下来维护一个01序列,表示第i位是否被弹出

    那么答案就是按照排序后序列求01区间和(其实有好多细节哦)

    取出一个数后置零即可

     1 #include<stdio.h>
     2 #include<stdlib.h>
     3 #include<string.h>
     4 #include<algorithm>
     5 #define LL long long
     6 using namespace std;
     7 int rank[101000],num[101000];
     8 int bit[101000],n;
     9 int lb(int x){
    10     return x&(-x);
    11 }
    12 int cmp(const int a,const int b){
    13     return num[a]>num[b];
    14 }
    15 LL q(int x){
    16     LL ans=0;
    17     while(x){
    18         ans+=bit[x];
    19         x-=lb(x);
    20     }
    21     return ans;
    22 }
    23 int c(int x,int v){
    24     while(x<=n){
    25         bit[x]+=v;
    26         x+=lb(x);
    27     }
    28     return 0;
    29 }
    30 int main(){
    31     int a,b;
    32     scanf("%d %d",&a,&b);
    33     n=a+b;
    34     for(int i=1;i<=n;i++)rank[i]=i;
    35     rank[0]=a;
    36     for(int i=a;i;--i)scanf("%d",&num[i]);
    37     for(int i=1;i<=b;i++)scanf("%d",&num[i+a]);
    38     sort(rank+1,rank+n+1,cmp);
    39     for(int i=1;i<=n;i++)c(i,1);
    40     LL ans=0;
    41     for(int i=1;i<=n;i++){
    42         if(rank[i]>rank[i-1])ans+=q(rank[i]-1)-q(rank[i-1]);
    43         else ans+=q(rank[i-1])-q(rank[i]);//????????????????rank?????
    44         c(rank[i],-1); 
    45     }
    46     printf("%lld
    ",ans);
    47     return 0; 
    48 }
    View Code
  • 相关阅读:
    border——边框属性
    CSS1,CSS2选择器详解
    CSS样式表与HTML结合的方法
    详细解析HTML基础结构
    jquery 解析xml
    asp.net js调用后台方法
    asp.net利用剪切板导出excel
    webform 不实用office控件导出excel StringBuilder 类型拼接字符串表格导出excel
    Android再学习-20141018-布局-进度条
    Android再学习-20140928-布局
  • 原文地址:https://www.cnblogs.com/Pumbit-Legion/p/5924425.html
Copyright © 2020-2023  润新知