HDU 4274 Spy's Work (树形DP,模拟)

时间:2025-02-17 11:06:32

题意: 

  给定一棵树,每个节点代表一个员工,节点编号小的级别就小,那么点1就是boss了。接下来给出对m个点的限制,有3种符号分别是op=“大于/小于/等于”,表示以第i个点为根的子树所有人的工资之和 大于/小于/等于 x,要求判断m个限制是否冲突了。注意每个员工的工资下限是1,而无上限。ps:可能出现对同个点多个限制,注意取交集。

思路:

  很水的题嘛,想复杂了。注意限制是针对整棵子树的!所以我们只需要算出这棵子树的范围,再判断是否和所给的限制有冲突,如果没有冲突的话还得取“所给限制”与“计算出的范围”的交集。在输入m个限制的时候注意可能已经冲突了,需先提前判断一下。注意可能需要用longlong,初始化时就将每个人的范围限制在[1,INF),这样就完事了~

 //#include <bits/stdc++.h>
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <deque>
#include <algorithm>
#include <vector>
#include <iostream>
#define pii pair<int,int>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define INF 0x7f7f7f7f
#define LL long long
using namespace std;
const double PI = acos(-1.0);
const int N=;
bool isWA;
int n, edge_cnt, head[N];
LL down[N], up[N];
struct node
{
int from, to, next;
node(){};
node(int from,int to,int next):from(from),to(to),next(next){};
}edge[N]; void add_node(int from,int to)
{
edge[edge_cnt]=node(from,to,head[from]);
head[from]=edge_cnt++;
} bool DFS(int t)
{
node e;
LL L=, R=INF; //计算此子树的范围
for(int i=head[t]; i!=-; i=e.next)
{
e=edge[i];
if(DFS(e.to)==false) return false;
L+=down[e.to];
} if(head[t]==-) //叶子,只要在[1,INF)都是合法的
{
if(up[t]>) return true;
else return false;
}
else
{
if( R<down[t] || L>up[t] ) return false; //无交集
down[t]=max(down[t], L); //更新本子树的范围
up[t]=min(up[t], R);
return true;
}
} void init(int n)
{
for(int i=; i<=n; i++) //注意初始化问题
down[i]=,
up[i]=INF,
head[i]=-;
isWA=false;
edge_cnt=;
} int main()
{
//freopen("input.txt", "r", stdin);
int n, m, a, d;char b,c;
while(~scanf("%d",&n))
{
init(n);
for(int i=; i<=n; i++)
{
scanf("%d",&a);
add_node(a,i);
}
scanf("%d",&m); for(int i=,L,R; i<m; i++)
{
scanf("%d%c%c%d",&a,&b,&c,&d);
L=, R=INF;
if(c=='<') R=d-;
else if(c=='>') L=d+;
else L=R=d;
if(L>up[a] || R<down[a]) isWA=true;//所给条件可能已经冲突
down[a]=L, up[a]=R;
}
if(!isWA && DFS()) puts("True");
else puts("Lie");
} return ;
}

AC代码