URAL - 2080 Wallet 树状数组+last数组

C - Wallet

  URAL - 2080 


Eugene is not a student struggling to pay his bills anymore. Now he lives in a big city and works for a well-known IT-company. He forgot the times when his wallet contained only his father’s credit card with no money on it; now it’s full with Eugene’s own various credit, discount and membership cards.
Every week Eugene follows the same routine: he visits the same places in the same order and talks with the same people. There is no place for surprises and complications in his life. Finally, after several months in a strange city, he can just perform a pre-determined order of actions and not trouble himself with anything.
However, Eugene does have one problem: sometimes in a store, restaurant or even at a subway station entrance he has to search his wallet for the right card for more than 5 seconds. Eugene hates to waste his precious time on that.
Cards in Eugene’s wallet are stored as a stack. Ha wants to be able to just take the top one every time he needs to pay or get a discount for something. After using a card he has no problem with inserting it in any position of the stack.
Knowing an order in which cards are going to be used throughout the week one can easily find a way to assemble them so that the top one will always be the right card to use. Eugene could have done that himself, but he doesn’t feel like solving this problem. You do it.
Input
The first line of the input contains two integers  n and  k (1 ≤  nk ≤ 10  5) — total number of cards Eugene has in his wallet and the number of times he uses them during the week. The cards are enumerated with integer numbers from 1 to  n.
The second line contains  k numbers  a  1a  2, …,  a  k (1 ≤  a  i ≤  n), separated by spaces: cards’ numbers in the order they are to be used.
Output
Output  k+1 lines.
The first line should contain  n card numbers separated by spaces from 1 to  n — the initial order of cards in the stack, from top to bottom.
The line number (  i + 1) should contain one number — how many cards will be located higher in the stack than the card  a  i after it has been used and returned into the wallet.
If there are several correct solutions, output any of them.
Example
input output
3 5
3 1 2 2 1
3 1 2 
2
1
0
1
0

Source URAL - 2080
My Solution 题意:给出一个数字序列,询问当前数字在本次与下次出现的区间里的 区间数字种数。 树状数组+last数组 具体见 UESTC 1342 郭大侠与甲铁城 树状数组+离线操作
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 2e5 + 8;
int q, n;
int value[maxn], last[maxn], ans[maxn], t[maxn];
int Tree[maxn];

struct Query{
    int l, r;
    int Index;
} querys[maxn];

bool cmp(const Query& a, const Query& b)
{
    return a.r < b.r;
}

inline int lowbit(int x)
{
    return (x&-x);
}

void add(int x, int value)
{
    for(int i = x; i <= q; i += lowbit(i))
        Tree[i] += value;
}

int get(int x)
{
    int sum = 0;
    for(int i = x; i; i -= lowbit(i))
        sum += Tree[i];
    return sum;
}
bool f[maxn];
int main()
{
    #ifdef LOCAL
    freopen("c.txt", "r", stdin);
    //freopen("c.out", "w", stdout);
    int T = 4;
    while(T--){
    #endif // LOCAL

    scanf("%d%d", &n, &q);
    for(int i = 1; i <= q; i++){
        scanf("%d", &value[i]);
        add(i, 1); t[value[i]] = q+1;
        if(!last[value[i]]) {last[value[i]] = i;}
    }
    for(int i = q; i >= 1; i--){
        querys[i].l = i+1;
        querys[i].r = t[value[i]]-1; t[value[i]] = i;
        querys[i].Index = i;
    }
    sort(querys + 1, querys + q + 1, cmp);
    int lastRight = 1;
    for(int i = 1; i <= q; i++){
        for(int j = lastRight; j <= querys[i].r; j++){
            if(last[value[j]] != j){
                add(last[value[j]], -1);
                last[value[j]] = j;
            }
        }
        lastRight = querys[i].r;
        ans[querys[i].Index] = get(querys[i].r) - get(querys[i].l - 1); //!这里注意减个1
    }
    printf("%d", value[1]); f[value[1]] = true;
    for(int i = 2; i <= q; i++){if(!f[value[i]]) {printf(" %d", value[i]); f[value[i]] = true;}}
    for(int i = 1; i <= n; i++){if(!f[i]) printf(" %d", i);}putchar('\n');
    for(int i = 1; i <= q; i++) printf("%d\n", ans[i]);


    #ifdef LOCAL
    cout << endl;
    }
    #endif // LOCAL
    return 0;
}

Thank you!                                                                                                                                              ------from  ProLights

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值