2080. Wallet
Time limit: 2.0 second
Memory limit: 256 MB
Memory limit: 256 MB
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 ≤
n,
k ≤ 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
1,
a
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.
Sample
input | output |
---|---|
3 5 3 1 2 2 1 | 3 1 2 2 1 0 1 0 |
给一列数,先输出出现顺序,再求相邻的相同数值的数之间有多少个不同的数值。
莫队算法在离线查询方面果然是无敌的!
#include <cstdio>
#include <iostream>
#include <string.h>
#include <string>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <bitset>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=100005,inf=0x3f3f3f3f;
const ll llinf=0x3f3f3f3f3f3f3f3f;
const ld pi=3.1415926535898L;
int a[maxn],ans[maxn],pre[maxn],t[maxn];
struct query{
int l,r,kuai;
};
query q[maxn];
bool cmp(query a,query b) {
return a.kuai<b.kuai || (a.kuai==b.kuai&&a.r<b.r);
}
int main() {
int n,k,i,j,flag=0,m=0;
scanf("%d%d",&n,&k);
mem0(pre);
int size=sqrt(n);
for (i=1;i<=k;i++) {
scanf("%d",&a[i]);
if (!pre[a[i]]) {
printf("%d ",a[i]);
} else {
q[++m].l=pre[a[i]];q[m].r=i-1;q[m].kuai=pre[a[i]]/size;
}
pre[a[i]]=i;
}
for (i=1;i<=n;i++) {
if (!pre[i]) printf("%d ",i);
}
printf("\n");
sort(q+1,q+m+1,cmp);
mem0(t);
memset(ans,-1,sizeof(ans));
int b=0,nl,nr;
for (i=q[1].l;i<=q[1].r;i++) {
if (!t[a[i]]) b++;
t[a[i]]++;
}
ans[q[1].l]=b-1;
nl=q[1].l;nr=q[1].r;
for (i=2;i<=m;i++) {
// cout << q[i].l << ' ' << q[i].r << endl;
while (nl<q[i].l) {
t[a[nl]]--;
if (t[a[nl]]==0) b--;
nl++;
}
while (nl>q[i].l) {
if (t[a[nl-1]]==0) b++;
t[a[nl-1]]++;
nl--;
}
while (nr>q[i].r) {
t[a[nr]]--;
if (t[a[nr]]==0) b--;
nr--;
}
while (nr<q[i].r) {
if (t[a[nr+1]]==0) b++;
t[a[nr+1]]++;
nr++;
}
ans[q[i].l]=b-1;
}
for (i=1;i<=k;i++) {
if (ans[i]==-1) printf("%d\n",n-1);
else printf("%d\n",ans[i]);
}
return 0;
}