F1. Omsk Metro (simple version)

题目链接:Problem - F1 - Codeforces

题目大意:有一棵树,然后通过 “+”,“?”, 其中“+”代表 将一个权重为xi的新节点添加到vi(xi,vi, 见输入介绍);“?”代表查询u, v, 里的简单路径是否有一个权重和正好等于ki的路径子段(可以为空)

有YES, 无NO,并题目保证为ui==1, 

输入:

  • 符号 "+"(不带引号),然后是两个数字 vi 和 xi ( xi∈{−1,1} ),也保证存在数字 vi 的顶点)。在这种情况下,权重为 xixi 的新站被添加到权重为 vi 的站中。
  • 符号"?"(不带引号),然后是三个数字 ui 、 vi 和 ki ( −n≤ki≤n )。可以保证数字 ui 和 vi 的顶点是存在的。在这种情况下,需要确定在站点 ui 和 vi 之间是否存在权重之和正好等于 ki 的路径子段(可能为空)。在这一版本的任务中,保证 ui=1.

具体题目点开链接查看

方法:动态规划, 离线查询

首先对于离线查询,要判断u到v里的简单路径里    是否存在有子段的 权重和 等于k, 由于xi = {1,-1} ,所以有结论,当满足k >= u到v里子段的最小值, k<=u到v里的子段最大值, 如果满足就YES, 否则NO.

而对于动态规划:首先题目保证了 u==1, 所以动态规划求的是到到每个结点v的最大子段和 与 最小子段和 才用数组存下来,方便后来的查询。 这里的具体实现,通过在树上的dfs, 然后选与不选,求得当前结点的最大与最小子段和。

其他细节:题目要求,其中“+”代表 将一个权重为xi的新节点添加到vi里, 此处里的新节点采用从根节点自增的方式获得。  然后由于存在空结点,所与最大与最小要与0比较。

#include 
#define IOS ios::sync_with_stdio(0);cin.tie(0), cout.tie(0)
using namespace std;
using pii = pair;
void solve(){
    int n;
    cin >> n;
    vector> g(n*2);
    vector a;
    vector dpmi(n*2), dpmx(n*2);
     // 乘二, 防止越界
    vector wi(n*2);

    wi[0] = 1;
    int cnt = 0;

    for(int i=0; i> op;
        if(op=='+') {
            int v, val;
            cin >> v >> val;
            v--, cnt++;
            g[v].push_back(cnt);
            wi[cnt] = val;
        }else{
            int u, v, k;
            cin >> u >> v >> k;
            u--,v--;
            a.push_back({v,k});
        }
    }
    //构建 最大,最小 子段和
    auto dfs = [&](auto&& dfs, int u,int fa, int mi, int mx)->void{
        mx = max(mx + wi[u], 0);
        mi = min(mi + wi[u], 0); 
        dpmi[u] = mi, dpmx[u] = mx; //以u结尾的最大最小子段和
        if(fa!=-1) {
            dpmx[u] = max(dpmx[u], dpmx[fa]); //不选该结点
            dpmi[u] = min(dpmi[u], dpmi[fa]);
        }
        for(int v : g[u])
            dfs(dfs, v, u, mi, mx);
    };

    dfs(dfs, 0, -1, 0,0);
    //离线查询
    for(auto [x,y] : a) {
        if(y >= dpmi[x] && y <= dpmx[x])cout << "YES\n";
        else cout << "NO\n";
    }

}
signed main(){
    IOS;
    int T = 1;
    cin >> T;
    while(T--) {
        solve();
    }
    return 0;
}

感谢你的观看与点赞收藏,欢迎大佬指正。 

你可能感兴趣的:(算法)