【LGR-052】洛谷9月月赛II(加赛)

题解:

没打。。。

ab题满世界都过了应该没什么意思

c题是个比较有意思的思维题(先看了题解才会的。。。)

我们考虑这么一件事情

没钥匙的人出门后

门一定是开着的

他进来的时候,门一定是开着的

其他时候,一定门能关着比较好

但是这个东西并不是很好维护,因为可能重复算

我们考虑重新排个序

我们把a[]在b[]前面的那个排在他前面

这样我们只需要记录一下上一个取了没有就可以了

感觉说出来不是很好理解这个东西。。。

d题还是个有点难度的数据结构题

一件比较显然的事情是我们对a的操作等价于是要

找当前x修改后是不是前缀最大值,以及他能延伸到哪(这个权值线段树显然可以维护)

然后就变成了区间覆盖成一个值了

然后 刚开始就想错了。。。

刚开始想的是去考虑这一段的值是怎么通过原先值变化的

其实这样反而不好做

直接去暴力统计现在的值

那么我们要知道的其实就是 当前区间>k的数的个数以及<k的数的乘积

这玩意我好像只会树套树或者cdq分治+排序+线段树。。。(写起来挺烦的啊)

于是复杂度就是nlog^2n了

不知道正解是怎么玩的。。。

代码:

c:

#include <bits/stdc++.h>
using namespace std;
#define rint register int
#define IL inline
#define rep(i,h,t) for (rint i=h;i<=t;i++)
#define dep(i,t,h) for (rint i=t;i>=h;i--)
const int N=3000;
const int INF=1e9;
struct re{
  int a,b,c,pos;
}a[N],b[N],c1[N],c2[N],p[N];
int pre[N],pos[N],x1[N],x2[N],f[N][N][2];
bool tt[N];
bool cmp(re x,re y)
{
  return x.b<y.b;
}
int main()
{
  freopen("1.in","r",stdin);
  freopen("1.out","w",stdout);
  ios::sync_with_stdio(false);
  int n,m;
  cin>>n>>m;
  rep(i,1,n)
  { 
    cin>>a[i].a>>a[i].b; a[i].pos=i;
    b[i*2-1].a=i*2-1; b[i*2-1].b=a[i].a;
    b[i*2].a=i*2; b[i*2].b=a[i].b;
  }
  sort(a+1,a+n+1,cmp);
  sort(b+1,b+2*n+1,cmp);
  rep(i,1,n) pos[a[i].pos]=i;
  rep(i,1,n*2)
  {
    if (b[i].a%2==0&&b[i-1].a%2==1)
      pre[b[i].a/2]=(b[i-1].a+1)/2;
    if (b[i].a%2==0) x2[b[i].a/2]=b[i].b-b[i-1].b;
    if (b[i].a%2==1) x1[(b[i].a+1)/2]=b[i+1].b-b[i].b;
  }
  int cnt=0;
  rep(i,1,n)
    if (!tt[i])
    {
      int x=i;
      p[++cnt].a=a[x].a; p[cnt].b=a[x].b; p[cnt].c=0; tt[i]=1;
      if (pos[pre[a[x].pos]]!=x) 
        c1[cnt].a=x1[a[x].pos],c1[cnt].b=x2[a[x].pos];
      else
        c1[cnt].a=x1[a[x].pos],c1[cnt].b=0;
      while (pos[pre[a[x].pos]]&&pos[pre[a[x].pos]]!=x)
      {
        x=pos[pre[a[x].pos]];
        tt[x]=1;
        p[++cnt].a=a[x].a; p[cnt].b=a[x].b; p[cnt].c=1;
        c1[cnt].a=x1[a[x].pos]; c1[cnt].b=x2[a[x].pos];
      }
    }
  rep(i,1,n)
    rep(j,0,m)
    {
      f[i][j][0]=f[i][j][1]=INF;
      if (p[i].c)
      {
        if (j) f[i][j][1]=min(f[i][j][1],min(f[i-1][j-1][1],f[i-1][j-1][0]));
        f[i][j][0]=min(f[i][j][0],f[i-1][j][0]+c1[i].b);
        f[i][j][0]=min(f[i][j][0],f[i-1][j][1]+c1[i].b+c1[i].a);
      } else
      {
        if (j) f[i][j][1]=min(f[i][j][1],min(f[i-1][j-1][1],f[i-1][j-1][0]));
        f[i][j][0]=min(f[i][j][0],f[i-1][j][0]+c1[i].b+c1[i].a);
        f[i][j][0]=min(f[i][j][0],f[i-1][j][1]+c1[i].b+c1[i].a);
      }
    }
  cout<<min(f[n][m][1],f[n][m][0]);
  return 0; 
}
原文地址:https://www.cnblogs.com/yinwuxiao/p/9694168.html