Codeforces Round #833 (Div. 2)
D. ConstructOR
知识点:高位和对低位无影响
一开始以为和广州的M一样,是数位dp,后来发现只要找到一个就行
果然无论什么时候都要看清题目
这时候还是没有什么思路,然后就看了题解的提示:当a和b有奇数时,d为偶数一定不可以
那显然这个结论可以继续推广,比较a,b,d的二进制后导0的大小即可
当a,b,d都截去d的后导0时,此时d为奇数
那么我们可以再次应用高位计算不会对低位产生影响这个条件
直接观察 \(a|b\) 如果当前第 \(i\) 位的 \(ans\) 与 \(a|b\) 不同时,
在这一位上加上 \(d<<i\) 即可对 \(ans\) 的第 \(i\) 位取反
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rep(i,l,r) for(int i=l;i<=r;i++)
ll a, b, d;
void solve()
{
cin >> a >> b >> d;
int w = __builtin_ctz(d);
if ((a & ((1 << w) - 1)) || (b & ((1 << w) - 1)))
{
cout << -1 << endl;
return;
}
a |= b;
a >>= w;
d >>= w;
ll ans(0);
for (int i = 0; (1ll << i) <= a; i++)
if ((ans ^ a) & (1 << i)) ans += d << i;
cout << (ans << w) << endl;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int T = 1;
cin >> T;
rep(i, 1, T) solve();
}
E. Yet Another Array Counting Problem
知识点:笛卡尔树上dp
看的大佬的题解,已经说的很清楚了,我就不献丑了
属实没想到能把题面这么转化,涨见识了
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define fi first
#define se second
#define pii pair<int,int>
#define rep(i,l,r) for(int i=l;i<=r;i++)
#define per(i,r,l) for(int i=r;i>=l;i--)
template<class T> using vc = vector<T>;
const ll mod = 1e9 + 7;
void solve()
{
int n, m;
cin >> n >> m;
vc<array<int, 2>> h(n + 1);
rep(i, 1, n) h[i][0] = h[i][1] = -1;
vc<int> a(n + 1);
rep(i, 1, n) cin >> a[i];
int sz = (int)log2(1.0 * n);
vc<vc<pii>> f(n + 1, vc<pii>(sz + 1));
rep(i, 1, n) f[i][0] = {a[i], i};
rep(j, 1, sz) for (int i = 1; i + (1 << j) - 1 <= n; i++)
{
pii a = f[i][j - 1];
pii b = f[i + (1 << (j - 1))][j - 1];
if (a.fi >= b.fi) f[i][j] = a;
else f[i][j] = b;
}
auto RMQ = [&](int l, int r)
{
int k = (int)log2(1.0 * r - l + 1);
pii a = f[l][k];
pii b = f[r - (1 << k) + 1][k];
if (a.fi >= b.fi) return a.se;
return b.se;
};
int rt = RMQ(1, n);
function<void(int, int, int)> build = [&](int rt, int l, int r)
{
if (l < rt)
{
int ls = RMQ(l, rt - 1);
h[rt][0] = ls;
build(ls, l, rt - 1);
}
if (r > rt)
{
int rs = RMQ(rt + 1, r);
h[rt][1] = rs;
build(rs, rt + 1, r);
}
};
build(rt, 1, n);
vc<vc<ll>> dp(n + 1, vc<ll>(m + 1));
function<void(int)> dfs = [&](int rt)
{
int ls = h[rt][0], rs = h[rt][1];
if (ls == -1 && rs == -1) rep(i, 1, m) dp[rt][i] = 1;
else if (rs == -1)
{
dfs(ls);
rep(i, 1, m - 1)
dp[rt][i + 1] = (dp[ls][i] + dp[rt][i]) % mod;
}
else if (ls == -1)
{
dfs(rs);
rep(i, 1, m)
dp[rt][i] = (dp[rs][i] + dp[rt][i - 1]) % mod;
}
else
{
dfs(ls), dfs(rs);
rep(i, 1, m)
{
dp[ls][i] = (dp[ls][i] + dp[ls][i - 1]) % mod;
dp[rs][i] = (dp[rs][i] + dp[rs][i - 1]) % mod;
}
rep(i, 1, m)
{
dp[rt][i] = (dp[rt][i - 1] + (dp[rs][i] - dp[rs][i - 1]) * dp[ls][i - 1]) % mod;
dp[rt][i] = (dp[rt][i] + dp[rs][i - 1] * (dp[ls][i - 1] - (i > 1 ? dp[ls][i - 2] : 0))) % mod;
}
}
};
dfs(rt);
ll ans(0);
rep(i, 1, m) ans = (ans + dp[rt][i]) % mod;
if (ans < 0) ans += mod;
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0);
int T; cin >> T;
rep(i, 1, T) solve();
return 0;
}
标签:rt,833,rs,int,rep,补题,Div,dp,ls
From: https://www.cnblogs.com/lunasama/p/16894460.html