p1822
高级数据结构?模拟吧?
题目自己理解,又一个考语文的题。
我们每次需要判断在xi上的大于yi的数有几个,以此更新答案,然后把他们都扔掉。如果yi不在上面要放上去。一眼看上去超级奇怪不知道上什么数据结构。
n^2的复杂度是不可以的,然而我见过的n*log2n的那些数据结构都用不上。
于是想到了开一个链表,每次找到连在开头的大于yi的第一个位置然后扔掉,更新之前的元素数量sum什么的。但是这样弄就很难做到log了。
但是既然连在开头的元素一定有序,我为什么要写链表呢?来个栈怎么样。
我们开一个数组o[i][f]表示第i个弦上第f位置放的音调是多少,LINK[i]表示第i个弦上一共放了多少触角。每次输入xi和yi判断:
如果o[xi][LINK[xi]]<yi说明还没有触角放在上面,ans++,LINK[xi]++,yi放在o[xi][1]里面;
如果o[xi][LINK[xi]==yi说明最大的就是自己,啥都不用移动,continue;
否则就要移去比自己大的触角,如果自己不在上面还要把自己放上去。我们去o[xi][f]里利用二分找第一个大于等于yi的位置find(),它就是自己的位置了,ans要加上LINK[xi]-find()。而且如果这个位置原来不等于yi还要ans+=2.
综上,本题一个栈+二分可A
二分的细节需要注意一下,返回的是自己的位置。
using namespace std; int i,f,xi,yi,ti; int n,p; int o[10][300010],LINK[10]; int ans; int l,r,mid; int find(int k,int x) { l=1; r=LINK[k]; while(l+1<r) { mid=(l+r)/2; if(o[k][mid]==x)return mid; if(o[k][mid]<x)l=mid; if(o[k][mid]>x)r=mid; } if(o[k][l]>=x)return l; else return r; } int main() { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); //freopen("123.in","r",stdin); n=read(),p=read(); for(i=1;i<=n;i++) { xi=read(),yi=read(); if(o[xi][LINK[xi]]<yi)//把自己移上去 { LINK[xi]++; o[xi][LINK[xi]]=yi; ans++; } else if(o[xi][LINK[xi]]==yi)//最大的就是我 continue; else if(o[xi][LINK[xi]]>yi)//安排一下 { ti=find(xi,yi); ans+=LINK[xi]-ti; if(o[xi][ti]!=yi) ans+=2; LINK[xi]=ti; o[xi][ti]=yi; } } cout<<ans; }