[bzoj4154][Ipsc2015]Generating Synergy

本文介绍了一种解决树上区间染色问题的算法实现,通过DFS序和线段树来处理节点染色及查询操作,支持动态更新颜色并查询指定节点颜色。

4154: [Ipsc2015]Generating Synergy

Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 306 Solved: 122
[Submit][Status][Discuss]
Description

给定一棵以1为根的有根树,初始所有节点颜色为1,每次将距离节点a不超过l的a的子节点染成c,或询问点a的颜色
Input

第一行一个数T,表示数据组数
接下来每组数据的第一行三个数n,c,q表示结点个数,颜色数和操作数
接下来一行n-1个数描述2..n的父节点
接下来q行每行三个数a,l,c
若c为0,表示询问a的颜色
否则将距离a不超过l的a的子节点染成c
Output

设当前是第i个操作,yi为本次询问的答案(若本次操作是一个修改则yi0),令zi=iyi,请输出z1+z2+...+zq109+7
Sample Input

1

4 3 7

1 2 2

3 0 0

2 1 3

3 0 0

1 0 2

2 0 0

4 1 1

4 0 0

Sample Output

32  

HINT

1,3,5,7的询问的答案分别为1,3,3,1,所以答案为 11+20+33+40+53+60+71=32.

数据范围:

对于100%的数据T<=6,n,m,c<=10^5,

1<=a<=n,0<=l<=n,0<=c<=c

因为只有子节点,所以把树上的每个点都对应到二维平面中取。
pos[x]表示xdfs序,deep[x]表示x的深度,每个点的坐标就是:(pos[x],deep[x])
染色就是给区间(L[a],R[a],deep[a],deep[a]+l)赋值。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define Mod 1000000007
const int N=100010;
struct E{int st,en;}aa[N<<1];
int T,n,m,tot,point[N],next[N<<1],pos[N],dfsn,deep[N],root,D,L[N],R[N];
struct S{
    int c,de,d[2],mi[2],ma[2],l,r;
    int &operator [] (int x){
        return d[x];
    }
    bool operator == (const S &x)const{
        return d[0]==x.d[0]&&d[1]==x.d[1];
    }
    bool operator < (const S &x)const{
        return d[D]==x.d[D]?d[D^1]<x.d[D^1]:d[D]<x.d[D];
    }
}tr[N],p[N],now;
inline int in(){
    int x=0;char ch=getchar();
    while(ch<'0'||ch>'9') ch=getchar();
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x;
}
inline void add(int x,int y){
    next[++tot]=point[x];point[x]=tot;
    aa[tot].st=x;aa[tot].en=y;
    next[++tot]=point[y];point[y]=tot;
    aa[tot].st=y;aa[tot].en=x;
}
inline void dfs(int x,int last){
    int i;
    L[x]=R[x]=pos[x]=++dfsn;
    for(i=point[x];i;i=next[i])
      if(aa[i].en!=last){
        deep[aa[i].en]=deep[x]+1;
        dfs(aa[i].en,x);
        R[x]=max(R[x],R[aa[i].en]);
      }
}
inline void update(int k){
    int l=tr[k].l,r=tr[k].r,i;
    for(i=0;i<=1;++i){
        tr[k].mi[i]=tr[k].ma[i]=tr[k][i];
        if(l){
            tr[k].mi[i]=min(tr[k].mi[i],tr[l].mi[i]);
            tr[k].ma[i]=max(tr[k].ma[i],tr[l].ma[i]);
        }
        if(r){
            tr[k].mi[i]=min(tr[k].mi[i],tr[r].mi[i]);
            tr[k].ma[i]=max(tr[k].ma[i],tr[r].ma[i]);
        }
    }
}
#define mid (l+r)/2
inline int build(int l,int r,int flag){
    if(l>r) return 0;
    D=flag;nth_element(p+l,p+mid,p+r+1);
    tr[mid]=p[mid];
    tr[mid].l=build(l,mid-1,flag^1);
    tr[mid].r=build(mid+1,r,flag^1);
    update(mid);
    return mid;
}
inline bool in(int k,int x1,int y1,int x2,int y2){
    return tr[k].mi[0]>=x1&&tr[k].ma[0]<=y1&&tr[k].mi[1]>=x2&&tr[k].ma[1]<=y2;
}
inline bool out(int k,int x1,int y1,int x2,int y2){
    return tr[k].mi[0]>y1||tr[k].ma[0]<x1||tr[k].mi[1]>y2||tr[k].ma[1]<x2;
}
inline bool in1(int k,int x1,int y1,int x2,int y2){
    return tr[k][0]>=x1&&tr[k][0]<=y1&&tr[k][1]>=x2&&tr[k][1]<=y2;
}
inline void pushdown(int k){
    int l=tr[k].l,r=tr[k].r,c=tr[k].de;
    if(l) tr[l].de=tr[l].c=c;
    if(r) tr[r].de=tr[r].c=c;
    tr[k].de=0;
}
inline void insert(int k,int x1,int y1,int x2,int y2,int c){
    if(x1>y1||x2>y2||!k) return ;
    if(in(k,x1,y1,x2,y2)){
        tr[k].de=tr[k].c=c;
        return ;
    }
    if(out(k,x1,y1,x2,y2)) return ;
    if(tr[k].de) pushdown(k);
    if(in1(k,x1,y1,x2,y2)) tr[k].c=c;
    int l=tr[k].l,r=tr[k].r;
    if(l&&tr[l].de!=c) insert(tr[k].l,x1,y1,x2,y2,c);
    if(r&&tr[r].de!=c) insert(tr[k].r,x1,y1,x2,y2,c);
}
inline int query(int k,int flag){
    if(now==tr[k]) return tr[k].c;
    if(tr[k].de) pushdown(k);
    if(now[flag]==tr[k][flag]){
        if(now[flag^1]<tr[k][flag^1]) return query(tr[k].l,flag^1);
        else return query(tr[k].r,flag^1);
    }
    else if(now[flag]<tr[k][flag]) return query(tr[k].l,flag^1);
    else return query(tr[k].r,flag^1);
}
int main(){
    T=in();
    while(T--){
        tot=dfsn=0;
        memset(point,0,sizeof(point));
        int i,x,j,y,z,ans=0;
        n=in();m=in();m=in();
        for(i=2;i<=n;++i){
            x=in();
            add(x,i);
        }
        dfs(1,0);
        for(i=1;i<=n;++i){
            p[i].c=1;
            p[i].de=0;
            p[i][0]=pos[i];
            p[i][1]=deep[i];
            for(j=0;j<=1;++j)
              p[i].mi[j]=p[i].ma[j]=p[i][j];
        }
        root=build(1,n,0);
        for(i=1;i<=m;++i){
            x=in();y=in();z=in();
            if(z) insert(root,L[x],R[x],deep[x],deep[x]+y,z);
            else{
                now[0]=pos[x];
                now[1]=deep[x];
                int c=query(root,0);
                ans=(ans+(int)(((LL)c*(LL)i)%Mod))%Mod;
            }
        }
        printf("%d\n",ans);
    }
}
【电动汽车充电站有序充电调度的分散式优化】基于蒙特卡诺和拉格朗日的电动汽车优化调度(分时电价调度)(Matlab代码实现)内容概要:本文介绍了基于蒙特卡洛和拉格朗日方法的电动汽车充电站有序充电调度优化方案,重点在于采用分散式优化策略应对分时电价机制下的充电需求管理。通过构建数学模型,结合不确定性因素如用户充电行为和电网负荷波动,利用蒙特卡洛模拟生成大量场景,并运用拉格朗日松弛法对复杂问题进行分解求解,从而实现全局最优或近似最优的充电调度计划。该方法有效降低了电网峰值负荷压力,提升了充电站运营效率与经济效益,同时兼顾用户充电便利性。 适合人群:具备一定电力系统、优化算法和Matlab编程基础的高校研究生、科研人员及从事智能电网、电动汽车相关领域的工程技术人员。 使用场景及目标:①应用于电动汽车充电站的日常运营管理,优化充电负荷分布;②服务于城市智能交通系统规划,提升电网与交通系统的协同水平;③作为学术研究案例,用于验证分散式优化算法在复杂能源系统中的有效性。 阅读建议:建议读者结合Matlab代码实现部分,深入理解蒙特卡洛模拟与拉格朗日松弛法的具体实施步骤,重点关注场景生成、约束处理与迭代收敛过程,以便在实际项目中灵活应用与改进。
### NOIP2015 运输计划 BZOJ4326 题解分析 #### 问题背景 该问题是经典的图论优化问题之一,主要考察树结构上的路径操作以及高效的数据处理能力。题目要求在一个由 $n$ 个节点组成的无向连通树中找到最优的一条边将其改造为虫洞(通过此边不需要耗费时间),从而使得给定的 $m$ 条运输路径中的最长耗时最小化。 --- #### 解决方案概述 解决这一问题的核心在于利用 **二分答案** 和 **树上差分技术** 的组合来实现高效的计算过程。以下是具体的技术细节: 1. **二分答案**: 设当前目标是最小化的最大路径长度为 $T_{\text{max}}$。我们可以通过二分的方式逐步逼近最终的结果。每次尝试验证是否存在一种方式将某条边改为虫洞后使所有路径的最大值不超过当前设定的目标值 $mid$[^1]。 2. **路径标记与统计**: 使用树上差分的思想对每一条路径进行标记并快速统计受影响的情况。假设两点之间的最近公共祖先 (Lowest Common Ancestor, LCA) 是 $r = \text{lca}(u_i, v_i)$,则可以在三个位置分别施加影响:增加 $(u_i + 1), (v_i + 1)$ 同时减少 $(r - 2)$。这种操作能够有效覆盖整条路径的影响范围,并便于后续统一查询和判断[^1]。 3. **数据结构支持**: 结合线段树或者 BIT (Binary Indexed Tree),可以进一步加速区间修改和单点查询的操作效率。这些工具帮助我们在复杂度范围内完成大量路径的同时更新和检索需求[^2]。 4. **实际编码技巧**: 实现过程中需要注意一些边界条件和技术要点: - 正确维护 DFS 序列以便映射原树节点到连续编号序列; - 准备好辅助函数用于快速定位 LCA 节点及其对应关系; - 编码阶段应特别留意变量初始化顺序及循环终止逻辑以防潜在错误发生。 下面给出一段基于上述原理的具体 Python 实现代码作为参考: ```python from collections import defaultdict, deque class Solution: def __init__(self, n, edges): self.n = n self.graph = defaultdict(list) for u, v, w in edges: self.graph[u].append((v, w)) self.graph[v].append((u, w)) def preprocess(self): """Preprocess the tree to get dfs order and lca.""" pass def binary_search_answer(self, paths): low, high = 0, int(1e9) best_possible_time = high while low <= high: mid = (low + high) // 2 if self.check(mid, paths): # Check feasibility with current 'mid' best_possible_time = min(best_possible_time, mid) high = mid - 1 else: low = mid + 1 return best_possible_time def check(self, limit, paths): diff_array = [0]*(self.n+1) for path_start, path_end in paths: r = self.lca(path_start, path_end) # Apply difference on nodes based on their relationship. diff_array[path_start] += 1 diff_array[path_end] += 1 diff_array[r] -= 2 suffix_sum = [sum(diff_array[:i]) for i in range(len(diff_array)+1)] # Verify whether any edge can be modified within given constraints. possible_to_reduce_max = False for node in range(1, self.n+1): parent_node = self.parent[node] if suffix_sum[node]-suffix_sum[parent_node]>limit: continue elif not possible_to_reduce_max: possible_to_reduce_max=True return possible_to_reduce_max # Example usage of class methods would follow here... ``` --- #### 总结说明 综上所述,本题的关键突破点在于如何巧妙运用二分策略缩小搜索空间,再辅以恰当的树形结构遍历技术和差分手段提升整体性能表现。这种方法不仅适用于此类特定场景下的最优化求解任务,在更广泛的动态规划领域也有着广泛的应用前景[^3]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值