欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【ISA的胡策】联校11.8(dp)

程序员文章站 2022-04-12 23:21:16
...

T1:

【ISA的胡策】联校11.8(dp)
【ISA的胡策】联校11.8(dp)

题解:

多队列排序。。。。
我记得很久以前做过“双栈排序”,因为是个栈,考虑两个数字不能在一个栈里的状况,ta比我大而且ta后面有比我小的数字,那恐怕就不能放在一个栈里,然后进行黑白图染色就好咯
我们同样考虑两个数字不能在一个队列里的情况,我们发现只要ta比我小就不能在一个队列里,按照上面的想法连边,我们发现ta只会往后连并且只连比自己小的,我们对于这个链取一个最长的就知道需要多少个队列了!
取一个最长。。。等等,这不就是个最长下降子序列而且是nlogn?
满分咯?

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
int g[50005];
int main()
{
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    int n,k,T,i,a;
    scanf("%d",&T);
    while (T--)
    {
        memset(g,0,sizeof(g));
        scanf("%d%d",&n,&k);
        int tot=0;
        for (i=1;i<=n;i++)
        {
            int l=1,r=tot;
            scanf("%d",&a);
            while (l<=r)
            {
                int mid=(l+r)>>1;
                if (g[mid]<=a) r=mid-1;
                else l=mid+1;
            }
            g[r+1]=a;
            tot=max(tot,r+1);
        }
        if (tot>k) printf("NO\n");else printf("YES\n");
    }
}

T2:

【ISA的胡策】联校11.8(dp)
【ISA的胡策】联校11.8(dp)

题解:

今天的T2大家全都爆0辣
正解来一波!
【ISA的胡策】联校11.8(dp)
【ISA的胡策】联校11.8(dp)

代码:

T3:

【ISA的胡策】联校11.8(dp)
【ISA的胡策】联校11.8(dp)

题解:

这个连边的方式可以用O(n)的单调栈
然后我用的方法是给询问排个序,这样以1为开始的都会在一起(栗子),我们对于这一堆以1为开始的询问求一波spfa,复杂度:???
然后就可以拿到30pts并(在30pts里)跑的飞快!
至于满分做法。。。。
十分毒瘤。。。。
要不我也不贴了吧。。。。
哎呀你竟然说我懒!
ISA学长的题解有两页啊喂!

代码:

30pts

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N=100005;
struct hh{int x,y,id;}e[N];
int h[N],n,m,l[N],r[N],stack[N];
int tot,nxt[N*2],point[N],v[N*2],dis[N],ans[N];
bool vis[N];
void addline(int x,int y)
{
    ++tot; nxt[tot]=point[x]; point[x]=tot; v[tot]=y;
    ++tot; nxt[tot]=point[y]; point[y]=tot; v[tot]=x;
}
int cmp(hh a,hh b){return a.x<b.x;}
void spfa(int s)
{
    queue<int>q;
    memset(dis,0x7f,sizeof(dis));
    q.push(s);
    dis[s]=0;
    memset(vis,0,sizeof(vis));
    while (!q.empty())
    {
        int now=q.front(); q.pop(); vis[now]=0;
        for (int i=point[now];i;i=nxt[i])
          if (dis[v[i]]>dis[now]+1)
          {
            dis[v[i]]=dis[now]+1;
            if (!vis[v[i]]) vis[v[i]]=1,q.push(v[i]);
          }
    }
}
int main()
{
    freopen("f.in","r",stdin);
    freopen("f.out","w",stdout);
    int i,top=0;
    scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++) scanf("%d",&h[i]),l[i]=1,r[i]=n;
    for (i=1;i<=n;i++)//右边达到的 
    {
        while (top&&h[stack[top]]<h[i])
        {
            addline(stack[top],i);
            top--;
        }
        stack[++top]=i;
    }
    top=0;
    for (i=n;i>=1;i--)//左边达到的 
    {
        while (top&&h[stack[top]]<h[i])
        {
            addline(stack[top],i);
            top--;
        }
        stack[++top]=i;
    }
    for (i=1;i<=m;i++) 
    {
        int x,y;
        scanf("%d%d",&x,&y);
        e[i].x=min(x,y); e[i].y=max(x,y);
        e[i].id=i;
    }
    sort(e+1,e+m+1,cmp);
    for (i=1;i<=m;i++)
      if (e[i].x!=e[i-1].x)
      {
        spfa(e[i].x);
        ans[e[i].id]=dis[e[i].y];
      }
      else ans[e[i].id]=dis[e[i].y];
    for (i=1;i<=m;i++) printf("%d\n",ans[i]);
}