noip23

T1

好吧,题目很sb,描述告诉你序列无限长,输入格式里告诉你m为序列长度,我:????,选择了相信后者。然后连暴力都挂分,可恶

这题一看就是个毒瘤数据结构题,思索了一下,发现就是个线段树,但我又想到了文艺平衡树,觉得可以用平衡树来解决,修改就是写个懒标记就好,稍作思索,再次选择了后者,再次炸裂,没调出来。把暴力交了,就走人了,也没打线段树。

正解:

好吧就是线段树下传懒标记。

其他解法乱搞

ODT:那就是模板了,因为数据是随的,所以可以过。

无旋treap:考场上没调出来,考后也没去改了,所以口胡一下,好像也什么好口胡的,将操作区间分出来,搞懒标记,输出答案时dfs来求这么搞的信心来自时限2s

好吧,其实是我菜了,这道题,感觉是考试题的强化版,就是询问不同,然后,它是有无旋treap解法的,果然还是太菜了。

T2

考场写贪心,结果只有30pts,别人的贪心都是70pts

好吧,题读错了已经不是第一次了,还是要细心些,我以为只能选喜欢的,但题意是挑m个,然后其中的一些物品是要被喜欢的。

正解:

首先将所有物品分成四类:

  • 两人都喜欢 \(s_{1}\)
  • 只有第一个人喜欢 \(s_{2}\)
  • 只有第二个人喜欢 \(s_{3}\)
  • 两人都不喜欢 \(s_{4}\)

如果没有共同喜欢,直接从 \(s_{2},s_{3}\) 里各拿k个,不够的话,就从剩下的里边挑最小的去补。

有共同喜欢,直接去枚举从\(s_{1}\) 里挑\(i\)个,然后计算当前的答案即可。

sb错误调一下午,\(s_{4}\)写成\(s_{3}\),最大值设小了,可恶
不过,刚知道有个叫LONG_LONG_MAX的东西,%%%语言大师LYM

Code
#include<cstdio>
#include<climits>
#include<algorithm>
#define MAX 200010
#define re register
#define int long long
#define INF LONG_LONG_MAX
namespace OMA
{
   int n,m,k,a,b,ans,v[MAX];
   int tmp[4],vis[MAX][4],sum[MAX][4];
   int s1[MAX],s2[MAX],s3[MAX],s4[MAX];
   inline int read()
   {
     int s=0,w=1; char ch=getchar();
     while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
     while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
     return s*w;
   }
   inline int min(int a,int b)
   { return a<b?a:b; }
   signed main()
   {
     //freopen("node.in","r",stdin);
     n = read(),m = read(),k = read();
     for(re int i=1; i<=n; i++)
     { v[i] = read(); }
     a = read();
     for(re int i=1; i<=a; i++)
     { vis[read()][0] = 1; }
     b = read();
     for(re int i=1; i<=b; i++)
     { vis[read()][1] = 1; }
     for(re int i=1; i<=n; i++)
     {
       if(vis[i][0]&&vis[i][1])
       { s1[++tmp[0]] = v[i]; }
       if(vis[i][0]&&!vis[i][1])
       { s2[++tmp[1]] = v[i]; }
       if(!vis[i][0]&&vis[i][1])
       { s3[++tmp[2]] = v[i]; }
       if(!vis[i][0]&&!vis[i][1])
       { s4[++tmp[3]] = v[i]; }
     }
     std::sort(s1+1,s1+1+tmp[0]),std::sort(s2+1,s2+1+tmp[1]);
     std::sort(s3+1,s3+1+tmp[2]),std::sort(s4+1,s4+1+tmp[3]);
     for(re int i=1; i<=tmp[0]; i++)
     { sum[i][0] = sum[i-1][0]+s1[i]; }
     for(re int i=1; i<=tmp[1]; i++)
     { sum[i][1] = sum[i-1][1]+s2[i]; }
     for(re int i=1; i<=tmp[2]; i++)
     { sum[i][2] = sum[i-1][2]+s3[i]; }
     for(re int i=1; i<=tmp[3]; i++)
     { sum[i][3] = sum[i-1][3]+s4[i]; }
     if(!tmp[0])
     {
       if(m<2*k)
       { printf("-1\n"); return 0; }
       int temp[MAX];
       for(re int i=k+1; i<=tmp[1]; i++)
       { temp[++temp[0]] = s2[i]; }
       for(re int i=k+1; i<=tmp[2]; i++)
       { temp[++temp[0]] = s3[i]; }
       for(re int i=1; i<=tmp[3]; i++)
       { temp[++temp[0]] = s4[i]; }
       std::sort(temp+1,temp+1+temp[0]);
       for(re int i=1; i<=m-2*k; i++)
       { ans += temp[i]; }
       printf("%lld\n",ans+sum[k][1]+sum[k][2]);
     }
     else
     {
       int ans = INF;
       int edge = min(m,min(k,tmp[0]));
       //printf("%lld\n",edge);
       for(re int i=0; i<=edge; i++)
       {
         if(2*k-i>m||k-i>tmp[1]||k-i>tmp[2])
         { continue ; }
         int temp = sum[i][0]+sum[k-i][1]+sum[k-i][2];
         //printf("%lld ",temp);
         if(2*k-i<m)
         { temp += sum[m-2*k+i][3]; }
         //printf("temp=%lld\n",temp);
         ans = min(ans,temp);
       }
       printf("%lld\n",ans);
     }
     return 0;
   }
}
signed main()
{ return OMA::main(); }

T3

考场乱写,0pts。

正解:

一个聪明的大脑

image

代码很简单,就是想不到。

Code
#include<bitset>
#include<cstdio>
#define N 410
#define MAX 50010
#define re register
namespace OMA
{
   int n,m,ans;
   int u[MAX],v[MAX];
   std::bitset<N>f[N],s;
   inline int read()
   {
     int s=0,w=1; char ch=getchar();
     while(ch<'0'||ch>'9'){ if(ch=='-')w=-1; ch=getchar(); }
     while(ch>='0'&&ch<='9'){ s=s*10+ch-'0'; ch=getchar(); }
     return s*w;
   }
   signed main()
   {
     n = read(),m = read();
     for(re int i=1; i<=m; i++)
     { u[i] = read(),v[i] = read(); }
     for(re int i=1; i<=n; i++)
     {
       s[i] = f[i][i] = 1;
       for(re int j=m; j; j--)
       {
         if(f[i][u[j]]&&f[i][v[j]])
         { s[i] = 0; break ; }
         else if(f[i][u[j]])
         { f[i][v[j]] = 1; }
         else if(f[i][v[j]])
         { f[i][u[j]] = 1; }
       }
     }
     for(re int i=1; i<=n; i++)
     {
       if(s[i])
       {
         for(re int j=i+1; j<=n; j++)
         {
           if(s[j]&&(f[i]&f[j]).none())
           { ans++; }
         }
       }
     }
     printf("%d\n",ans);
     return 0;
   }
}
signed main()
{ return OMA::main(); }
posted @ 2021-07-25 10:53  -OMA-  阅读(83)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end