Codeforces Round #362 (Div. 2)(A~D))

目前水平有限,补了四题。。。
感觉这场质量很高,没有白补。
A. Pineapple Incident
题意&思路:水题

#include<bits/stdc++.h>
using namespace std;

int main(){
    int t,s,x;
    while(cin>>t>>s>>x){
      if(x==t||(x-t)%s==0&&x>t||(x-t-1)%s==0&&(x-t-1>0)) printf("YES\n");
      else printf("NO\n");
    }
}

B. Barnicle
题意&思路:字符串模拟一下科学计数法转换,注意下细节。
这几个数据容易错:
8.77056e6
7.0e100
1.0e0
0.0e10

#include<bits/stdc++.h>
using namespace std;
int main(){
   string s;
   while(cin>>s){
      int nz=0,a,e,b=0,ok=0;
      a=s[0]-'0';
      for(int i=2;i<s.size();i++){
          if(s[i]=='e') { e=i;ok=1;}
          else if(!ok&&s[i]>='1'&&s[i]<='9') nz=i;
          else if(ok) b=b*10+s[i]-'0';
      }
      ok=0;
      if(a||b==0) { cout<<a;ok=1;}
      if(b>=nz-1){
         for(int i=2;i<=nz;i++){
            if(ok||s[i]!='0') cout<<s[i],ok=1;
         }
         if(nz==0) nz=1;
         for(int i=0;i<b-nz+1;i++) cout<<0;
         cout<<endl;
      }
      else{
         for(int i=2;i<b+2;i++){
            if(ok||s[i]!='0') cout<<s[i],ok=1;
         }
         cout<<".";
         for(int i=b+2;i<=nz;i++) cout<<s[i];
         cout<<endl;
      }
   }
}

C. Lorenzo Von Matterhorn
题意:在一棵根为1的二叉搜索树上(每个点的子孙是他的两倍和两倍+1),在这个树上更新任意两点之间的边的权值,和询问树上任意两点之间边之和。
思路:在一棵二叉搜索树上,边之间点都是2^n增加,所以直接暴力复杂度O(logn),范围10^18,
就用map。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
map<ll,ll>m;
int main(){
     int q;cin>>q;
     m.clear();
     while(q--){
        ll o,u,v;cin>>o>>u>>v;
        if(o==1){
            ll w;cin>>w;
            while(u!=v){
                if(u>v) swap(u,v);
                m[v]+=w;
                v/=2;
            }
        }
        else{
            ll ans=0;
            while(u!=v){
                if(u>v) swap(u,v);
                ans+=m[v];
                v/=2;
            }
            cout<<ans<<endl;
        }
     }
}

D.Puzzles
题意:给你一棵树,然后让你从1点dfs,但是dfs的时候如果有多个结点,那么则随机选一个结点去访问,最后问你每个点访问时间的期望,假设访问一个结点用时1s。
思路:
案例
分析一颗子树:

当前已知节点1的期望为1.0 ->anw[1]=1.0
需要通过节点1递推出节点2、4、5的期望值

1的儿子分别是2、4、5,那么dfs序所有可能的排列是6种:
1:1-2-4-5 (2、4、5节点的儿子没有写出)
2:1-2-5-4
3:1-4-2-5
4:1-4-5-2
5:1-5-2-4
6:1-5-4-2
这六种情况分别:
都有一部分:2都是从1转移过来,首先共有ans[1]+1;
第二部分:当节点1到达节点2的时候贡献是0,种类分别对应(1、2)
当先到达节点4后到节点2的时候贡献(size(4)+size(4)+szie(5)),种类分别对应(3、4)
当先到达节点5后到节点2的时候贡献(size(5)+size(5)+size(4)),种类分别对应(5、6)
而所有的排列对于的概率都是1/6,所以第二部分的贡献就是(0+size(4)*3+size(5)*3)/6 = (size(4)+size(5))/2=(size(1)-size(6)-1)/2
多找几棵子树就可以发现 对于第二部分求法有推导: ans[v]=(size(u)-size(v)-1)/2
可以这样理解:对于v点,当走到他的父亲u点时,它可以选择最优一步到v,即贡献为0,也可以最差,走完u点其他所有点后最后到v,即贡献度为size[u]-size[v]-1;

#include<bits/stdc++.h>
using namespace std;
template<int N,int M>//N点的个数,M边的个数
struct Graph
{
    int top;
    struct Vertex{
        int head;
    }V[N];
    struct Edge{
        int v,next;
    }E[M];
    void init(){
        memset(V,-1,sizeof(V));
        top = 0;
    }
    void add_edge(int u,int v){
        E[top].v = v;
        E[top].next = V[u].head;
        V[u].head = top++;
    }
};
Graph<100000+10,100000*2+10> g;
int sum[100000+10];
double ans[100000+10];
void dfs1(int u,int f){
   sum[u]=1;
   for(int i=g.V[u].head;i!=-1;i=g.E[i].next){
      int v=g.E[i].v;
      if(v==f) continue;
      dfs1(v,u);
      sum[u]+=sum[v];
   }
}

void dfs2(int u,int f){
   for(int i=g.V[u].head;i!=-1;i=g.E[i].next){
      int v=g.E[i].v;
      if(v==f) continue;
      ans[v]=ans[u]+1.0+(sum[u]-sum[v]-1)*0.5;
      dfs2(v,u);
   }
}

int main(){
    int n;
    while(~scanf("%d",&n)){
        g.init();
        memset(sum,0,sizeof(sum));
        for(int i=2;i<=n;i++){
            int x;scanf("%d",&x);
            g.add_edge(x,i);
            g.add_edge(i,x);
        }
        memset(ans,0,sizeof(ans));
        dfs1(1,-1);
        ans[1]=1.0;
        dfs2(1,-1);
        for(int i=1;i<n;i++) printf("%.2f ",ans[i]);
        printf("%.2f\n",ans[n]);
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值