zoukankan      html  css  js  c++  java
  • 【NOIP2018模拟赛】

    A. 【NOIP2018模拟赛】刺客信条(AC)

    这道题第一眼看上去可能会想到找路径然后算距离,但发现这是不现实的。

    所以我们通过限定答案的值来判断是否满足。

    将答案设为 r (半径) ,每个棋盘上的点都由半径做圆,然后判断路径不触碰到圆的最大半径。

    我们利用并查集将每个圆与墙进行处理,然后通过二分答案进行判断。

    p.s. 记得要加eps (一个极小的数,调整精度)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef double db;
     4 
     5 const db e=1e-4;
     6 const int N=2011;
     7 int n,m,k,fa[N];
     8 db x[N],y[N],dis[N][N];
     9 
    10 int getf(int x){
    11     if(fa[x]==x) return x;
    12     else return fa[x]=getf(fa[x]);
    13 }
    14 
    15 void exchange(int x,int y){
    16     fa[getf(x)]=getf(y);
    17 }
    18 
    19 db two(db a){
    20     return a*a;
    21 }
    22 
    23 db d(int i,int j){
    24     return sqrt(two(x[i]-x[j])+two(y[i]-y[j]));
    25 }
    26 
    27 bool pd(double r){
    28     for(int i=1;i<=k+4;i++) fa[i]=i;
    29     for(int i=1;i<=k;i++){
    30         if(r-x[i]>e) exchange(k+1,i);//左墙 
    31         if(r-y[i]>e) exchange(k+2,i);//底墙 
    32         if(r-(n-x[i])>e) exchange(k+3,i);//右墙 
    33         if(r-(m-y[i])>e) exchange(k+4,i);//顶墙 
    34         for(int j=i+1;j<=k;j++){
    35             if(r*2-dis[i][j]>e || (fabs(r*2-dis[i][j])<e)) exchange(i,j);
    36         } 
    37     }
    38     if(getf(k+1)==getf(k+2)) return true;
    39     if(getf(k+1)==getf(k+3)) return true;
    40     if(getf(k+2)==getf(k+4)) return true;
    41     if(getf(k+3)==getf(k+4)) return true;
    42     return false;
    43 }
    44 
    45 int read(){
    46     int x=0,f=1;
    47     char s=getchar();
    48     while(!isdigit(s)) f*=(s=='-')? -1:1,s=getchar();
    49     do x=(x<<1)+(x<<3)+(s^48),s=getchar();
    50     while(isdigit(s));
    51     return x*f;
    52 }
    53 
    54 int main(){
    55     n=read(),m=read(),k=read();
    56     for(int i=1;i<=k;i++){
    57         scanf("%lf%lf",&x[i],&y[i]);
    58     }
    59     for(int i=1;i<=k;i++){
    60         for(int j=i+1;j<=k;j++){
    61             dis[i][j]=d(i,j);
    62         }
    63     }
    64     db l=0,r=1000000;
    65     while(r-l>e){
    66         db mid=(l+r)/2;
    67         if(pd(mid)) r=mid;
    68         else l=mid;
    69     }
    70     printf("%.2f",l);
    71     return 0;
    72 } 

    C. 【NOIP2018模拟赛】传送门 (portal)

    一道树形dp的题。

    设f[][]表示状态

    f[x][0]:x和x的子树里没有传送门
    f[x][1]:x和x的子树里有传送门

    状态转移方程:
    f[x][0]+=f[y][0]+2*w[i];

    f[x][1]+=min(f[y][0]+w[i]-d[y],f[y][1]+w[i]*2);

    code

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int MAXN=1e6+5;
     4 const long long null=1e15;
     5 
     6 int n;
     7 int head[MAXN],to[MAXN*2],next[MAXN*2],w[MAXN*2],cnt;
     8 long long f[MAXN][2],d[MAXN];
     9 
    10 void add(int u,int v,int l){
    11     cnt++;
    12     next[cnt]=head[u];
    13     to[cnt]=v;
    14     w[cnt]=l;
    15     head[u]=cnt;
    16 }
    17 
    18 void dp(int x,int fa){
    19     for(int i=head[x];i;i=next[i]){
    20         int y=to[i];
    21         if(y==fa)
    22             continue;
    23         dp(y,x);
    24         d[x]=max(d[x],d[y]+w[i]);
    25         f[x][0]+=f[y][0]+2*w[i];
    26         f[x][1]+=min(f[y][0]+w[i]-d[y],f[y][1]+w[i]*2);
    27     }
    28 }
    29 
    30 int main(){
    31     cin>>n;
    32     for(int i=1;i<n;i++){
    33         int u,v,a;
    34         scanf("%d%d%d",&u,&v,&a);
    35         add(u,v,a);
    36         add(v,u,a);
    37     }
    38     dp(1,1);
    39     cout<<min(f[1][1],f[1][0]);
    40     return 0;
    41 }

    B. 【NOIP2018模拟赛】黑暗之魂(darksoul)

    这是一颗环套树

    题目要求的是这棵环套树的直径,再+1就是答案了。

    我们把该环提出来,在上面操作。

    那么直径要么是环上某点的子树内直径,要么是环上某两点子树内最长链再加一段环上路径。

    子树内直径和最长链我们先算出来,剩下的就是如何求出环上两点使之匹配出来最大值。

    枚举环上一点 i ,同时维护一个指针 j  往后指,表示从 i+1  到 j  是近一些,而 j 之后的点呢会绕环一圈来走回 i  更近一些。

    那么 i+1  到 j的我们用一个单调队列来求最大值,绕一周的用一个后缀最大值算就好了。

      1 #include<cstdio>
      2 #include<cctype>
      3 using namespace std;
      4 typedef long long ll;
      5 const int N=1e6+5;
      6 int tot=1,top,qx,qy,node;
      7 ll ans,mx;
      8 bool pd;
      9 int first[N],nex[N<<1],en[N<<1],w[N<<1];
     10 int st[N],dfn[N],d[N],len[N],col[N],q[N];
     11 ll suf[N],pre[N],f[N];
     12 bool bz[N];
     13 inline int read(){
     14     int x=0,f=1;
     15     char s=getchar();
     16     while(!isdigit(s)) f*=(s=='-')? -1:1,s=getchar();
     17     do x=(x<<1)+(x<<3)+(s^48),s=getchar();
     18     while(isdigit(s));
     19     return x*f;
     20 }
     21 inline ll max(ll x,ll y)
     22 {
     23     return x>y?x:y;
     24 }
     25 inline void in(int x,int y,int z)
     26 {
     27     nex[++tot]=first[x];
     28     first[x]=tot;
     29     en[tot]=y;
     30     w[tot]=z;
     31 }
     32 void dfs(int x,int y)
     33 {
     34     st[++top]=x;
     35     dfn[x]=top;
     36     for(int i=first[x];i && !pd;i=nex[i])
     37         if(i^y)
     38         {
     39             if(dfn[en[i]])
     40             {
     41                 for(int j=dfn[en[i]];j<=top;j++)
     42                 {
     43                     d[++d[0]]=st[j];
     44                     bz[st[j]]=true;
     45                 }
     46                 pd=true;
     47                 return;
     48             }
     49             dfs(en[i],i^1);
     50         }
     51     top--;
     52 }
     53 void find(int x,int y,ll z,ll &num)
     54 {
     55     if(z>num) num=z;
     56     for(int i=first[x];i;i=nex[i])
     57         if(en[i]^y && en[i]^x) find(en[i],x,z+w[i],num);
     58 }
     59 void get(int x,int y)
     60 {
     61     if(y==d[0]) return;
     62     for(int i=first[x];i;i=nex[i])
     63         if(en[i]==d[y+1])
     64         {
     65             len[y]=w[i];
     66             get(en[i],y+1);
     67         }
     68 }
     69 void dg(int x,int y,ll z)
     70 {
     71     if(z>mx) mx=z,node=x;
     72     col[x]=tot;
     73     for(int i=first[x];i;i=nex[i])
     74         if(en[i]^y && en[i]^x && !bz[en[i]]) dg(en[i],x,z+w[i]);
     75 }
     76 void dg1(int x,int y,ll z)
     77 {
     78     if(z>mx) mx=z,node=x;
     79     for(int i=first[x];i;i=nex[i])
     80         if(en[i]^y && en[i]^x && col[en[i]]==tot) dg1(en[i],x,z+w[i]);
     81 }
     82 int main()
     83 {
     84     int n=read();
     85     for(int i=1;i<=n;i++)
     86     {
     87         int x=read(),y=read(),z=read();
     88         in(x,y,z);
     89         in(y,x,z);
     90     }
     91     dfs(1,0);
     92     tot=0;
     93     for(int i=1;i<=d[0];i++)
     94     {
     95         for(int j=first[d[i]];j;j=nex[j])
     96             if(!bz[en[j]]) find(en[j],d[i],w[j],f[i]);
     97         node=mx=0;
     98         tot++;
     99         dg(d[i],0,0);
    100         dg1(node,0,0);
    101         ans=max(ans,mx);
    102         if(f[i]>ans) ans=f[i];
    103     }
    104     get(d[1],1);
    105     for(int i=first[d[d[0]]];i;i=nex[i])
    106         if(en[i]==d[1])
    107         {
    108             len[d[0]]=w[i];
    109             break;
    110         }
    111     for(int i=2;i<=d[0];i++) pre[i]=pre[i-1]+len[i-1];
    112     for(int i=2;i<=d[0];i++) suf[i]=pre[d[0]]+len[d[0]]-pre[i]+f[i];
    113     for(int i=d[0]-1;i>1;i--) suf[i]=max(suf[i+1],suf[i]);
    114     int l=1,r=0;
    115     for(int i=1,j=1;i<d[0];i++)
    116     {
    117         while(l<r && q[l]<=i) l++;
    118         while(j<d[0] && pre[j+1]-pre[i]<=pre[d[0]]-pre[j+1]+len[d[0]]+pre[i])
    119         {
    120             j++;
    121             while(l<=r && f[q[r]]+pre[q[r]]<=f[j]+pre[j]) r--; 
    122             q[++r]=j;
    123         }
    124         ll num=0;
    125         if(j<d[0]) num=suf[j+1]+pre[i];
    126         if(i<j) num=max(num,f[q[l]]+pre[q[l]]-pre[i]);
    127         ans=max(ans,num+f[i]);
    128     }
    129     printf("%lld",ans+1);
    130     return 0;
    131 }
  • 相关阅读:
    ES5、6对异步事件的处理方式
    SQL技巧
    前端技巧
    docker start 启动失败,logs 没有日志
    mysql使用存储过程insert
    Spring 手动回滚事务/提交事务,及通过
    mysql触发器trigger 实例详解
    @PostConstruct 之NullException
    springboot 2 多数据源 hikari 连接池
    swagger 日期Date
  • 原文地址:https://www.cnblogs.com/lirh04/p/12392524.html
Copyright © 2011-2022 走看看