# [2021-9-23] supplementary question record

Keywords: Algorithm data structure dp CodeForces

Educational Codeforces Round 54 (Rated for Div. 2)
E. Vasya and a Tree
Main idea of the topic: given a tree with 1 as the root node, each node value is 0, given several modifications, x,d,v, is the y value of X node and its dist (x, y) < = D, plus v, and finally outputs the value of each node; Solution: for offline modification, use the tree array to make a difference in the depth on the tree. Remember to modify it back during backtracking to avoid the impact of this sub path on another sub path.

```#include<bits/stdc++.h>
#define pb push_back
#define se second
#define fi first
#define mp make_pair
using namespace std;
typedef long long ll;
const int N = 3e5 + 5;
#define debug(x) cout << #x <<" is " << x << endl
struct Fenwik_Tree{
vector<ll> bit;
int n;
Fenwik_Tree(int _n):n(_n),bit(_n + 1,0){
}
void update(int pos,ll val){
for(int i = pos;i <= n; i += i & (-i)){
bit[i] += val;
}

}
ll query(int x){
ll ans = 0;
for(int i = x;i > 0;i -= i & (-i))
ans += bit[i];
return ans;
}
};
int n,m;
vector<int> g[N];
ll ans[N];

void dfs(int u,int pre,int dep,Fenwik_Tree & b){
//cout <<u << endl;
ll d = it.fi;
ll w = it.se;
b.update(dep,w);
b.update(dep + d + 1,-w);
}
ans[u] = b.query(dep);
for(int v : g[u])if(v != pre)dfs(v,u,dep + 1,b);
ll d = it.fi;
ll w = it.se;
b.update(dep,-w);
b.update(dep + d + 1,w);
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n;
for(int i = 1;i <= n - 1;i++){
int u,v;
cin >> u >> v;
g[u].pb(v);
g[v].pb(u);
}
Fenwik_Tree b(n);

cin >> m;
for(int i = 1;i <= m;i++){
ll v,d,w;
cin >> v >> d >> w;
}
dfs(1,-1,1,b);
for(int i = 1;i <= n;i++)
cout << ans[i] <<" \n"[i == n];
return 0;
}
```

G. Array Game
Two people play the game alternately, choose a[i:i +m] a value greater than 0, jump over and subtract one. Whoever can't do this operation will lose; This kind of problem should grasp the state of winning and losing. We consider the state that ai-1 faces (because it is convenient to consider the state that ai-1 faces at first, and it is convenient to consider the state faced by ai-1 at first). If [i + 1 ~i + m] has a "must fail" state, we will jump to let the opponent face the "must lose" state, and I is the "must win state"; Otherwise, when all the states are in the winning state, (a[i] - 1)%2 == 1 is in the winning state (because the opponent must jump to [i + 1,i + m] and subtract 1 to face the winning state), otherwise it is in the losing state; because the number of States is small and up to (1 < < 5), the segment tree can be used to optimize the states of each zone followed by different states. The state transition of this interval can be expressed as follows:`

```for(int j = 0;j < all;j++){
nodes[x].s[j] = nodes[lc(x)].s[nodes[rc(x)].s[j]];
}
```

Considering the interval update, adding even numbers can be skipped directly, and adding odd numbers is to negate the interval, which can be directly exchanged with the result of processing the inversion of the interval;

```#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 5;
typedef long long ll;
int n,m,q;

struct status{
int s[1<<5];
};
ll a[N];
int all;
struct Segment_Tree{
#define lc(x) (x<<1)
#define rc(x) (x<<1)|1
status nodes[N << 2][2];
int lazy[N << 2];
void init(int x,int t,int v){
for(int i = 0;i < all;i++){
if(i != all - 1 || v % 2 == 1)nodes[x][t].s[i] = (i >> 1) + (1 << (m - 1));
else nodes[x][t].s[i] = (i >> 1);
}
}
void up(int x){
for(int i = 0;i <= 1;i++){
for(int j = 0;j < all;j++){
nodes[x][i].s[j] = nodes[lc(x)][i].s[nodes[rc(x)][i].s[j]];
}
}
}
void rev(int x){
lazy[x] ^= 1;
for(int i = 0;i < all;i++)
swap(nodes[x][0].s[i],nodes[x][1].s[i]);
}
void down(int x){
if(lazy[x] == 0)return;
rev(lc(x));
rev(rc(x));
lazy[x] = 0;
}
void build(int x,int l,int r){
lazy[x] = 0;
if(l == r){
init(x,0,(a[l] - 1) % 2);
init(x,1,((a[l] - 1) % 2) ^ 1);
return;
}
int mid = (l + r) >> 1;
build(lc(x),l,mid);
build(rc(x),mid + 1,r);
up(x);
}
void update(int x,int cur_l,int cur_r,int l,int r){
if(cur_l >= l && cur_r <= r){
rev(x);
return;
}
down(x);
int mid = (cur_l + cur_r) >> 1;
if(l <= mid)
update(lc(x),cur_l,mid,l,r);
if(r >= mid + 1)
update(rc(x),mid + 1,cur_r,l,r);
up(x);
}
status query(int x,int cur_l,int cur_r,int l,int r){
if(l <= cur_l && r >= cur_r){
return nodes[x][0];
}
down(x);
int mid = (cur_l + cur_r) >> 1;
if(r <= mid)
return query(lc(x),cur_l,mid,l,r);
else if(l >= mid + 1)
return query(rc(x),mid + 1,cur_r,l,r);
else{
status sl = query(lc(x),cur_l,mid,l,r);
status sr = query(rc(x),mid + 1,cur_r,l,r);
status ans;
for(int i = 0;i < all;i++){
ans.s[i] = sl.s[sr.s[i]];
}
return ans;
}
}
}seg;
int main(){
//ios::sync_with_stdio(false);
//	cin.tie(0);
//cout.tie(0);
scanf("%d%d%d",&n,&m,&q);

all = (1 << m);
for(int i = 1;i <= n;i++){
scanf("%lld",&a[i]);
}
seg.build(1,1,n);
for(int i = 1;i <= q;i++){
int op,l,r;
//cin >> op >> l >> r/;
scanf("%d%d%d",&op,&l,&r);
if(op == 1){
ll d;
scanf("%lld",&d);
if(d & 1)seg.update(1,1,n,l,r);
}else{
status s = seg.query(1,1,n,l,r);
if((s.s[all - 1] >> (m - 1)) & 1)
printf("1\n");
else
printf("2\n");
}
}
return 0;
}
```

Codeforces Round #521 (Div. 3)
F2. Pictures with Kittens (hard version)
Main idea of the topic: select x numbers from n numbers, and each adjacent K number must be selected. Considering that dp[i][j] is the selected j number and ends with I, the transfer equation is dp[i][j] = max(dp[i - k][j - 1] ~ dp[i - 1][j - 1]) + a[i] , use the monotone queue to optimize the interval maximum value. Maintain monotone decrement here. The queue head is the maximum value. The maintenance is divided into three steps: 1. Eliminate the queue head that exceeds the range; 2. Eliminate the tail that is less than the current value (further and smaller, useless); 3. Add the current value to the tail queue. After optimization, it is n^2 (segment tree n2logn timeout)

```#include<bits/stdc++.h>
#pragma GCC optimize("Ofast")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#define debug(x) cout<<#x<<" is "<<x<<endl
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define DBG 0
const int N = 5000 + 5;
typedef long long ll;
const int INF = 0x3f3f3f3f;
const ll LLINF = (1LL<<60);
using namespace std;
const int mod = 998244353;
ll fast_pow(ll a,ll b){ll ans = 1;while(b){if(b&1)ans = (ans * a)%mod;a = (a * a)%mod;b>>=1;}return (ans%mod);}
inline ll read(){ll X=0; bool flag=1; char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') flag=0; ch=getchar();}while(ch>='0'&&ch<='9') {X=(X<<1)+(X<<3)+ch-'0'; ch=getchar();}if(flag) return X;return ~(X-1);}
inline void write(ll X){if(X<0) {X=~(X-1); putchar('-');}if(X>9) write(X/10);putchar(X%10+'0');}
typedef pair<int,int> pii;
typedef vector<int> vi;
inline void fastIO(){ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);}
inline void time_cost(clock_t start_time,clock_t end_time){cout << "The run time is: " <<(double)(end_time - start_time) / CLOCKS_PER_SEC << "s" << endl;}
inline void init(){

}
ll n,k,x;
ll dp[N][N];
ll a[N];
int que[N];
int ta,he;
inline void solve(){
init();
scanf("%lld%lld%lld",&n,&k,&x);
for(int i = 1;i <= n;i++)scanf("%lld",&a[i]);
ll ans = 0;
if(x > n || x < n / k ){
printf("-1\n");
return;
}
for(int i = 0;i <= n;i++)
for(int j = 0;j <= x;j++)
dp[i][j] = -LLINF;
dp[0][0] = 0;
for(int j = 1;j <= x;j++){
que[0] = 0;
if(j == 1)ta = 1,he = 0;
else ta = 0,he = 0;
for(int i = 1;i <= n;i++){

while(he < ta && que[he] < i - k)he++;
if(he < ta){
dp[i][j] = dp[que[he]][j - 1] + a[i];
if(j == x && n - i + 1 <= k)ans = max(ans,dp[i][j]);
}
while(he < ta && dp[i][j - 1] >= dp[que[ta - 1]][j - 1])ta--;
que[ta++] = i;
}
}
printf("%lld\n",ans);
return;
}
int main(){
//fastIO();
#if DBG
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
#endif
solve();

return 0;
}
```

Posted by daniel_lee_hill on Thu, 23 Sep 2021 01:05:23 -0700