C. Yet Another Card Deck
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You have a card deck of n cards, numbered from top to bottom, i. e. the top card has index 1 and bottom card — index n. Each card has its color: the i-th card has color ai.
You should process q queries. The j-th query is described by integer tj. For each query you should:
find the highest card in the deck with color tj, i. e. the card with minimum index;
print the position of the card you found;
take the card and place it on top of the deck.
Input
The first line contains two integers n and q (2≤n≤3⋅105; 1≤q≤3⋅105) — the number of cards in the deck and the number of queries.
The second line contains n integers a1,a2,…,an (1≤ai≤50) — the colors of cards.
The third line contains q integers t1,t2,…,tq (1≤tj≤50) — the query colors. It’s guaranteed that queries ask only colors that are present in the deck.
Output
Print q integers — the answers for each query.
Example
inputCopy
7 5
2 1 1 4 3 3 1
3 2 1 1 4
outputCopy
5 2 3 1 5
Note
Description of the sample:
the deck is [2,1,1,4,3–,3,1] and the first card with color t1=3 has position 5;
the deck is [3,2–,1,1,4,3,1] and the first card with color t2=2 has position 2;
the deck is [2,3,1–,1,4,3,1] and the first card with color t3=1 has position 3;
the deck is [1–,2,3,1,4,3,1] and the first card with color t4=1 has position 1;
the deck is [1,2,3,1,4–,3,1] and the first card with color t5=4 has position 5.
思路:
只看第一个!!!
刚开始我还以为要用线段树,写到中间才发现。
对这种模拟超时的题目,有一个想法是对的:我们总要忽略一些东西,可能是顺序什么的,也可能是这里的不是第一个就不记!
顺便复习了一下线段树,感觉好sbqwq
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<math.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<sstream>
#include<vector>
#include<map>
#include<set>
#include<ctype.h>
#include<stack>
#include<queue>
#ifdef LOCAL
FILE*FP=freopen("text.in","r",stdin);
//FILE*fp=freopen("text.out","w",stdout);
#endif
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
#define _forplus(i,a,b) for( register int i=(a); i<=(b); i++)
#define _forsub(i,a,b) for( register int i=(a); i>=(b); i--)
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define INF 0x3f3f3f3f
const double pi=acos(-1);
int n,q,p,a,b,m,x,y,ans;
struct node
{
int l,r,w,s,f=0;//w:颜色,s:序号,f:权值
}tree[1200001];
int first[55]={0};
int cnt=0;
inline void build(int k,int ll,int rr)//建树
{
tree[k].l=ll,tree[k].r=rr;
if(tree[k].l==tree[k].r)
{
scanf("%d",&tree[k].w);
cnt++;
if(!first[tree[k].w])first[tree[k].w]=cnt;
tree[k].s=cnt;
return;
}
int m=(ll+rr)/2;
build(k*2,ll,m);
build(k*2+1,m+1,rr);
//tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
inline void down(int k)//标记下传
{
tree[k*2].f+=tree[k].f;
tree[k*2+1].f+=tree[k].f;
tree[k*2].w+=tree[k].f*(tree[k*2].r-tree[k*2].l+1);
tree[k*2+1].w+=tree[k].f*(tree[k*2+1].r-tree[k*2+1].l+1);
tree[k].f=0;
}
inline void ask_point(int k)//单点查询
{
if(tree[k].l==tree[k].r)
{
ans=tree[k].w;
return ;
}
if(tree[k].f) down(k);
int m=(tree[k].l+tree[k].r)/2;
if(x<=m) ask_point(k*2);
else ask_point(k*2+1);
}
inline void change_point(int k)//单点修改
{
if(tree[k].l==tree[k].r)
{
tree[k].w+=y;
return;
}
if(tree[k].f) down(k);
int m=(tree[k].l+tree[k].r)/2;
if(x<=m) change_point(k*2);
else change_point(k*2+1);
tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
inline void ask_interval(int k)//区间查询
{
if(tree[k].l>=a&&tree[k].r<=b)
{
ans+=tree[k].w;
return;
}
if(tree[k].f) down(k);
int m=(tree[k].l+tree[k].r)/2;
if(a<=m) ask_interval(k*2);
if(b>m) ask_interval(k*2+1);
}
inline void change_interval(int k)//区间修改
{
if(tree[k].l>=a&&tree[k].r<=b)
{
tree[k].w+=(tree[k].r-tree[k].l+1)*y;
tree[k].f+=y;
return;
}
if(tree[k].f) down(k);
int m=(tree[k].l+tree[k].r)/2;
if(a<=m) change_interval(k*2);
if(b>m) change_interval(k*2+1);
tree[k].w=tree[k*2].w+tree[k*2+1].w;
}
int main()
{
scanf("%d",&n);//n个节点
scanf("%d",&m);//m种操作
build(1,1,n);//建树
for(int i=1;i<=m;i++)
{
scanf("%d",&p);//颜色
printf("%d",first[p]);
if(i!=m)putchar(' ');
_forplus(j,1,50){
if(first[j]<first[p])first[j]++;
}
first[p]=1;
}
}