zoukankan      html  css  js  c++  java
  • 9.17题解

    我们搬家了,被从政新正心这两个字似乎是这么写的楼驱逐到了扬帆楼,回到了级部的视线范围内

    T1

    考场上并没有发现什么性质,就用二分答案加$set$贪心水了过去,如果二分答案,那么我们对于每个人一定是去找远离终点方向上可以打的最远的怪去打,这样的话给别的人留下的合法的机会就更多,如果这个怪在远离终点的方向上没有怪可打了,就找靠近终点方向上最近的怪去打,如果两个方向上都没有可打的合法的怪了,直接$return$ $false$就可以了,分为在终点左边的和右边的两种情况,搞一搞就可以了,复杂度是$O(nlognlogAns)$,$Ans$代表答案区间,$n$是每次$check$时枚举每个人,$logn$是$set$自带的,毒瘤出题人并没有把最大的数据放在最后一组,导致我并没有看到最大的,然后我数组就开小了,我就$RE90$了我太难了

    正解似乎是个dp

     1 #include<set>
     2 #include<cmath>
     3 #include<cstdio>
     4 #include<iostream>
     5 #include<algorithm>
     6 #define maxn 25100
     7 #define maxm 50100
     8 #define int long long
     9 #define inff 3000000000
    10 #define inf 2000000000000000000
    11 using namespace std;
    12 int n,m,S,l,r=inff,ans=inf;
    13 int p[maxn],q[maxm];
    14 set <int> s;
    15 bool check(int len)
    16 {
    17     s.clear();
    18     for(int i=1;i<=m;++i)  s.insert(q[i]);
    19     for(int i=1;i<=n;++i)
    20     {
    21         if(p[i]>S)  break;
    22         set<int>::iterator pos=s.lower_bound(p[i]);
    23         set<int>::iterator ls=pos;
    24         if(*pos<p[i]&&p[i]-*pos+abs(S-*pos)>len)  return 0;
    25         if(*ls>p[i])  ls--;//远离s处的点,先找到最近的一个
    26         //远离s的方向找最远的,靠近s的方向找最近的
    27         if(pos==s.begin()||p[i]-*ls+S-*ls>len)
    28         {
    29             if(*pos-p[i]+abs(S-*pos)>len)  return 0;
    30             else  s.erase(*pos);
    31             continue;
    32         }
    33         while(1)
    34         {
    35             if(p[i]-*ls+S-*ls>len)  {ls++;  break;}
    36             else
    37             {
    38                 if(ls==s.begin())  break;
    39                 ls--;
    40             }
    41         }
    42         s.erase(*ls);    
    43     }
    44     for(int i=n;i>=1;--i)
    45     {
    46         if(p[i]<S)  break;
    47         set<int>::iterator pos=s.lower_bound(p[i]);
    48         if(pos==s.end()||*pos-p[i]+abs(S-*pos)>len)
    49         {
    50             pos--;
    51             if(p[i]-*pos+abs(S-*pos)>len)  return 0;
    52             else  s.erase(*pos);
    53             continue;
    54         }
    55         while(1)
    56         {
    57             if(*pos-p[i]+*pos-S>len)  {pos--;  break;}
    58             else
    59             {
    60                 pos++;
    61                 if(pos==s.end())  {pos--;  break;}
    62             }
    63         }
    64         s.erase(*pos);
    65     }
    66     return 1;
    67 }
    68 signed main()
    69 {
    70     scanf("%lld%lld%lld",&n,&m,&S);
    71     for(int i=1;i<=n;++i)  scanf("%lld",&p[i]);
    72     for(int i=1;i<=m;++i)  scanf("%lld",&q[i]);
    73     sort(p+1,p+n+1);
    74     while(l<r)
    75     {
    76         if(l==r-1)
    77         {
    78             if(check(l))  ans=min(ans,l);
    79             else  ans=min(ans,r);
    80             break;
    81         }
    82         int mid=(l+r)>>1;
    83         if(check(mid))  {ans=min(ans,mid);  r=mid;}
    84         else  l=mid+1;
    85     }
    86     printf("%lld
    ",ans);
    87     return 0;
    88 }
    View Code

    T2

    容易发现我一定是尽量让每一个点都往上配,走的越向上,对答案的贡献就越大,而是谁走上去的并不重要,所以我们可以在$dfs$的过程中,尽量的让每个点都沿着他的父亲向上走,如果在当前子树外面的点少于$k$个了,就证明这个子树中的一些点必须留下,就让可以配的点继续向上配就可以了,也算是个贪心吧

     1 #include<iostream>
     2 #include<cstdio>
     3 #define maxn 100100
     4 #define int long long
     5 using namespace std;
     6 int n,k,a,js,ans;
     7 int head[maxn],to[maxn*2],xia[maxn*2];
     8 int pd[maxn],size[maxn];
     9 void add(int x,int y)
    10 {
    11     to[++js]=y;  xia[js]=head[x];  head[x]=js;
    12 }
    13 void dfs(int x)
    14 {
    15     pd[x]=1;
    16     for(int i=head[x];i;i=xia[i])
    17     {
    18         int ls=to[i];
    19         if(pd[ls])  continue;
    20         dfs(ls);
    21         if(size[ls]<=k)  ans+=size[ls];
    22         else  ans+=2*k-size[ls];
    23         size[x]+=size[ls];
    24     }
    25 }
    26 signed main()
    27 {
    28     //freopen("beauty.in","r",stdin);
    29     scanf("%lld%lld%lld",&n,&k,&a);
    30     for(int i=1;i<=2*k;++i)  {int v;  scanf("%lld",&v);  size[v]=1ll;}
    31     for(int i=1;i<n;++i)
    32     {
    33         int u,v;  scanf("%lld%lld",&u,&v);
    34         add(u,v);  add(v,u);
    35     }
    36     dfs(1);  printf("%lld
    ",ans);
    37     return 0;
    38 }
    View Code

    正解看起来还是个dp的样子

    T3

    听说是树剖,我不会,本来想打部分分,结果一直过不去样例,就死了

    咕咕咕咕咕咕咕咕咕咕.........

  • 相关阅读:
    4.9cf自训9..
    数位dp-入门模板题 hdu2089
    熟能生巧 汽车停车入位技巧解析-倒车入库--侧边停车
    MyBatis参数传入集合之foreach动态sql
    jquery如何判断checkbox(复选框)是否被选中
    Mybatis关联查询(嵌套查询)
    Mysql 分页语句Limit用法
    $.ajax返回的JSON格式的数据后无法执行success的解决方法
    JavaWeb学习总结(十二)——Session
    Spring MVC中Session的正确用法之我见
  • 原文地址:https://www.cnblogs.com/hzjuruo/p/11644489.html
Copyright © 2011-2022 走看看