ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

A层邀请赛4

2022-07-29 07:31:47  阅读:100  来源: 互联网

标签:int top son dep read include 邀请赛


A. 暗之链锁

树剖维护一下即可,其实树上差分也可

注意线段树空间开四倍!!!!!!!!!!

左移\(2\)

code
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
typedef long long ll;
inline int read(){
    int x = 0; char c = getchar();
    while(c < '0' || c > '9')c = getchar();
    do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while(c >= '0' && c <= '9');
    return x;
}
const int maxn = 100005;
int head[maxn],tot,n,m;
struct edge{
    int to, net;
}e[maxn << 1 | 1];
void add(int u, int v){
    e[++tot].net = head[u];
    head[u] = tot;
    e[tot].to = v;
}
int id[maxn],dep[maxn],fa[maxn],son[maxn],top[maxn],size[maxn],nid[maxn];
int cnt[maxn];
struct tree{
    int t[maxn << 2 | 1];
    void push_down(int x){
        t[x << 1] += t[x];
        t[x << 1 | 1] += t[x];
        t[x] = 0;
    }
    void modify(int x,int l, int r, int L, int R){
        if(L <= l && r <= R){
            ++t[x];
            return;
        }
        if(t[x])push_down(x);
        int mid = ( l + r) >> 1;
        if(L <= mid)modify(x << 1, l, mid, L, R);
        if(R > mid)modify(x << 1 | 1, mid + 1, r, L , R);
    }
    void query(int x, int l, int r){
        if(l == r){
            cnt[nid[l]] = t[x];
            return;
        }
        if(t[x])push_down(x);
        int mid = (l + r) >> 1;
        query(x << 1, l ,mid);
        query(x << 1 | 1, mid + 1, r); 
    }
}T;
void dfs1(int x){
    size[x] = 1;
    for(int i = head[x]; i; i = e[i].net){
        int v = e[i].to;
        if(v == fa[x])continue;
        dep[v] = dep[x] + 1;
        fa[v] = x;
        dfs1(v);
        size[x] += size[v];
        if(size[v] > size[son[x]])son[x] = v;
    }
}
int tim;
void dfs2(int x, int tp){
    id[x] = ++tim; nid[tim] = x;
    top[x] = tp;
    if(son[x])dfs2(son[x],tp);
    for(int i = head[x]; i; i = e[i].net){
        int v = e[i].to;
        if(v == fa[x] || v == son[x])continue;
        dfs2(v, v);
    }
}
void work(){
    int u = read(), v = read();
    while(top[u] != top[v]){
        if(dep[top[u]] < dep[top[v]])swap(u, v);
        T.modify(1, 1, n, id[top[u]], id[u]);
        u = fa[top[u]];
    }
    if(u == v)return;
    if(dep[u] < dep[v])swap(u ,v);
    T.modify(1, 1, n, id[v] + 1, id[u]);
}
int main(){
    n = read(), m = read();
    for(int i = 1; i < n; ++i){
        int u = read(), v = read();
        add(u, v);add(v, u);
    }
    dep[1] = fa[1] = 1;dfs1(1);dfs2(1,1);
    for(int i = 1; i <= m; ++i)work();
    T.query(1, 1, n);
    ll ans = 0;
    for(int i = 2; i <= n; ++i){
        if(cnt[i] == 1)++ans;
        if(cnt[i] == 0)ans += m;
    }
    printf("%lld\n",ans);
    return 0;
}

B. 蚊子

这题告诉我优秀的题意转化是多么重要

杀死的概率不好求,但是存活的概率好求,用总数减去存活的期望就是杀死的期望

那么如何求存活的期望,发现问题可以转化为求树上任意两个叶子的路径的权值乘积,其中深度\(>=d\)的权值为1,小于等于\(d\)的权值为每次存活的概率

然后树\(DP\)就比较显然了,请读者自证

code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
char xch,xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
inline int read(){
	int x=0,f=1;char ch=getc();
	while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getc();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
	return x*f;
}
const int maxn = 5000005;
const int mod = 1e9 + 7;
int head[maxn],tot,n;
struct edge{
    int to, net;
}e[maxn << 1 | 1];
void add(int u, int v){
    e[++tot].net = head[u];
    head[u] = tot;
    e[tot].to = v;
}
ll qpow(ll x, ll y){
    ll ans = 1;
    for(;y;y >>= 1, x = x * x % mod)if(y & 1)ans = ans * x % mod;
    return ans; 
}
int d;
ll qw, g[maxn], p, q, ans, m;
void dfs(int x, int fa, int dep){
    bool is = 1;
    for(register int i = head[x]; i; i = e[i].net){
        int v = e[i].to;
        if(v == fa)continue;
        dfs(v, x, dep + 1);
        is = 0;
        g[x] += g[v];
    }
    if(is)g[x] = 1, ++m;
    else g[x] %= mod;
    ll now = dep <= d ? qw : 1;
    for(register int i = head[x]; i; i = e[i].net){
        int v = e[i].to;
        if(v == fa)continue;
        ans = (ans + g[v] * (g[x] - g[v] + mod) % mod * now) % mod;
    }
    g[x] = g[x] * now % mod;
}
int main(){
    n = read();
    for(register int i = 1; i < n; ++i){
        int u = read(), v = read();
        add(u, v);add(v, u);
    }
    d = read(),p = read(), q = read();
    qw = (1 - qpow(q, mod - 2) * p % mod + mod) % mod;
    dfs(1, 1, 0);
    printf("%lld\n",((m * (m - 1) % mod - ans) % mod + mod) % mod);
    return 0;
}

标签:int,top,son,dep,read,include,邀请赛
来源: https://www.cnblogs.com/Chencgy/p/16530951.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有