【树状数组】洛谷 P3605 Promotion Counting P
2021-06-03 22:15:00
# ACM
—–
题链
–解法一
跑一边$dfs$序,按照权值大小对$n$个点从大到小排好遍历,对于第$i$个点只要求它子树的和就行;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
| #include <bits/stdc++.h> using namespace std; #define ls rt<<1 #define rs rt<<1|1 #define LL long long #define PI acos(-1.0) #define eps 1e-8 #define Pair pair<double,double>
#define mod 998244353 #define MAXN 1e18 #define MS 100009
LL n,m; struct node{ LL val,id; }a[MS]; LL b[MS],tb; LL dfn[MS]; LL sz[MS]; vector<LL > vc[MS]; LL p[MS]; queue<LL > Q; LL ac[MS]; LL tot;
bool cmp(node t1,node t2){ return t1.val > t2.val; }
LL lowbit(LL x){ return x&(-x); }
void add(LL pos,LL val){ for(;pos<=n;pos+=lowbit(pos)) p[pos] += val; }
LL query(LL pos){ LL ans = 0; for(;pos;pos-=lowbit(pos)) ans += p[pos]; return ans; }
void dfs(LL x){ dfn[x] = ++tot; sz[x] = 1; for(auto &i:vc[x]){ dfs(i); sz[x] += sz[i]; } }
int main() { ios::sync_with_stdio(false); cin >> n; for(int i=1;i<=n;i++){ cin >> a[i].val; a[i].id = i; b[i] = a[i].val; } sort(b+1,b+n+1); tb = 1; for(int i=2;i<=n;i++){ if(b[i] != b[i-1]) b[++tb] = b[i]; } for(int i=1;i<=n;i++){ a[i].val = lower_bound(b+1,b+tb+1,a[i].val) - b; } sort(a+1,a+n+1,cmp); for(int i=2;i<=n;i++){ LL x; cin >> x; vc[x].push_back(i); } dfs(1); for(int i=1;i<=n;i++){ node t = a[i]; LL tl = dfn[t.id]; LL tr = tl+sz[t.id]-1; LL ans = query(tr) - query(tl); ac[t.id] = ans; add(dfn[t.id],1); } for(int i=1;i<=n;i++){ cout << ac[i] << "\n"; }
return 0; }
|
–解法二
离散化+树状数组,$dfs$求解;
$dfs$时,每碰到一个点就将它的权值记录在树状数组中,此时会有一个问题,有两颗子树互不影响,记两颗子树的头节点为$t1,t2$,$dfs$时会先遍历第一颗子树,此时到第二颗时,显然第二颗也就是$t2$的答案应该与之前维护的权值无关,此时可以两眼一闭查一下树状数组中比$t2$大的个数,然后把$t2$的子节点全部遍历完后再查一次比$t2$大的个数,两次的差值就是$t2$的答案;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| #include <bits/stdc++.h> using namespace std; #define ls rt<<1 #define rs rt<<1|1 #define LL long long #define PI acos(-1.0) #define eps 1e-8 #define Pair pair<double,double>
#define mod 998244353 #define MAXN 1e18 #define MS 100009
LL n,m; LL a[MS]; LL b[MS],tb; vector<LL > vc[MS]; LL p[MS]; LL ac[MS];
LL lowbit(LL x){ return x&(-x); }
void add(LL pos,LL val){ for(;pos<=n;pos+=lowbit(pos)) p[pos] += val; }
LL query(LL pos){ LL ans = 0; for(;pos;pos-=lowbit(pos)) ans += p[pos]; return ans; }
void dfs(LL x){ ac[x] = -(query(n) - query(a[x])); for(auto &i:vc[x]){ dfs(i); } ac[x] += query(n) - query(a[x]); add(a[x],1); }
int main() { ios::sync_with_stdio(false); cin >> n; for(int i=1;i<=n;i++){ cin >> a[i]; b[i] = a[i]; } sort(b+1,b+n+1); tb = 1; for(int i=2;i<=n;i++){ if(b[i] != b[i-1]) b[++tb] = b[i]; } for(int i=1;i<=n;i++){ a[i] = lower_bound(b+1,b+tb+1,a[i]) - b; } for(int i=2;i<=n;i++){ LL x; cin >> x; vc[x].push_back(i); } dfs(1); for(int i=1;i<=n;i++){ cout << ac[i] << "\n"; }
return 0; }
|
2021-06-03 22:15:00
# ACM