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;
}
原文地址:https://www.cnblogs.com/qywyt/p/9523651.html