Educational Codeforces Round 54 (Rated for Div. 2)
E. Vasya and a Tree
题目大意:给定一棵以1为根节点的树,每个节点值为0,给定若干修改,x,d,v,为x节点及其dist(x,y)<=d的子节点y,值加上v,最后输出各节点的值;解法:离线修改,使用树状数组在树上对深度进行差分,记得回溯时修改回来,避免这条子路径对另一条子路径产生影响。
#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];
vector<pair<ll,ll> > ask[N];
ll ans[N];
void dfs(int u,int pre,int dep,Fenwik_Tree & b){
//cout <<u << endl;
for(auto it : ask[u]){
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);
for(auto it : ask[u]){
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;
ask[v].pb(mp(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
题目大意:两个人交替玩游戏,选择a[i:i +m]一个大于0的值跳过去并减一,谁不能进行这样的操作谁就输了;这种题目要抓住必胜态和必败态,我们考虑ai-1后所面对的状态(因为一开始在a1就先-1了,考虑ai - 1所面对的状态比较方便),若[i + 1 ~i + m]存在必败态,那么跳过去让对手面对必败态,i为必胜态;否则当全部为必胜态时,(a[i] - 1)%2 == 1为必胜态(因为要让对手必须跳到[i + 1,i + m]并减1,让自身面对必胜态)否则为必败态;由于状态数量很少最多(1 << 5),可以用线段树优化出每个区间后接不同状态,该区间的状态;状态转移可以如下表示:`
for(int j = 0;j < all;j++){
nodes[x].s[j] = nodes[lc(x)].s[nodes[rc(x)].s[j]];
}
考虑区间更新的情况,加偶数可以直接跳过,加奇数就是对区间进行取反,可以与处理出区间取反的结果,直接交换;
#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)
题目大意:从n个数里选x个数,每相邻的k个数必须要有一个被选中,考虑dp[i][j]为选j个数且以i为结尾,那么转移方程为dp[i][j] = max(dp[i - k][j - 1] ~ dp[i - 1][j - 1]) + a[i],使用单调队列优化一下区间最大值,在这里维护单调递减,队首为最大值,维护分为三步:1、把队首超过范围的剔除,2、将尾部小于当前值的剔除(更远且更小,没用)3、将当前值加入尾部队列,优化后为n^2,(线段树n2logn超时)
#include<bits/stdc++.h>
#pragma comment(linker, "/stack:200000000")
#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;
}