We hope you enjoyed these problems!
Author: Lyz09
Consider the case where $$$k=1$$$.
#include<iostream>
using namespace std;
int t,n;
int main()
{
cin>>t;
while(t--)
{
cin>>n;
bool ans=false;
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(x==100)
ans=true;
}
if(ans)
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
}
}
Author: lizhous
Consider for a given $$$p$$$, which elements can be placed at $$$p$$$ with one reversal operation.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#define int long long
using namespace std;
int n,a,x,m,sum;
priority_queue <int> nm[2];
bool hv[2];
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int T;
cin>>T;
while(T--)
{
sum=0;
hv[0]=hv[1]=0;
while(!nm[0].empty()) nm[0].pop();
while(!nm[1].empty()) nm[1].pop();
cin>>n>>m;
for(int i=1;i<=n;i++)
{
cin>>a;
nm[i&1].push(a);
sum+=a;
}
for(int i=1;i<=m;i++)
{
cin>>x;
if((!nm[x&1].empty()&&nm[x&1].top()>=0)||!hv[x&1])
{
sum-=nm[x&1].top();
nm[x&1].pop();
hv[x&1]=1;
}
}
cout<<sum<<"\n";
}
}
Author: ma2021tyoi0037
Consider how to determine whether the median of an interval equals $$$x$$$.
What could be the median of each subsequence?
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=5e3+10;
int n,a[N],b[N],mid,dp[N];
void run(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
memcpy(b+1,a+1,n<<2);
sort(b+1,b+n+1);
mid=b[(n+1)>>1];
for(int i=1;i<=n;i++){
if(a[i]==mid){
a[i]=0;
continue;
}
a[i]=(a[i]>mid?1:-1);
}
for(int i=1,flg=0;i<=n;i++){
dp[i]=0;
flg=!a[i];
if(flg and (i==1 or dp[i-1]))dp[i]=dp[i-1]+1;
for(int j=i-3,sm=a[i];j>=0;j-=2){
flg+=!a[j+1];
flg+=!a[j+2];
sm+=a[j+1]+a[j+2];
if(abs(sm)>=flg or (j and !dp[j]))continue;
dp[i]=max(dp[i],dp[j]+1);
}
// cout<<dp[i]<<" \n"[i==n];
}
cout<<dp[n]<<'\n';
}
int main(){
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
int T;
cin>>T;
while(T--)run();
}
2222D - Permutation Construction
Author: Lyz09
Try to perform a prefix sum on $$$a$$$.
Consider what the upper bound of the answer is.
#include<iostream>
#include<algorithm>
using namespace std;
#define N 200010
int t,n,a[N],p[N];
pair<long long,int> b[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--)
{
cin>>n;
b[0].first=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
b[i].first=b[i-1].first+a[i];
b[i].second=i;
}
for(int i=n;i>=1;i--)
b[i].first=b[i-1].first;
sort(b+1,b+n+1);
for(int i=n;i>=1;i--)
p[b[i].second]=n-i+1;
for(int i=1;i<=n;i++)
cout<<p[i]<<" \n"[i==n];
}
}
Author: Lyz09
Try to use $$$0$$$ and $$$2^n-1$$$ in the solution.
#include<iostream>
#include<set>
using namespace std;
int t,n;
set<long long> s;
int makeI(long long x)
{
cout<<"I "<<x<<endl;
int ans=0;
cin>>ans;
return ans;
}
int makeQ(long long y)
{
cout<<"Q "<<y<<endl;
int ans=0;
cin>>ans;
return ans;
}
int query(long long x)
{
int res=makeQ(x);
for(long long w:s)
if(w>=x)
res--;
return res;
}
long long guess(int n)
{
long long pre=0;
for(int i=n-1;i>=0;i--)
if(query(pre|(1ll<<i))>0)
{
pre|=(1ll<<i);
}
return pre;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n;
s.clear();
cout<<0<<endl;
s.insert(0);
int res1=makeI(0);
if(res1==1)
{
makeI((1ll<<n)-1);
long long w=guess(n);
cout<<"A "<<1<<" "<<w<<endl;
continue;
}
long long c=guess(n);
s.insert(c);
if(c==(1ll<<n)-1)
{
int res2=makeI(1);
if(res2!=res1)
{
cout<<"A "<<3<<" "<<c<<endl;
}
else
{
cout<<"A "<<2<<" "<<c<<endl;
}
continue;
}
int res2=makeI((1ll<<n)-1);
if(query((1ll<<n)-1)>0)
{
cout<<"A "<<2<<" "<<c<<endl;
}
else
{
cout<<"A "<<3<<" "<<c<<endl;
}
}
}
Author: hzy_____ Preparation: Rebex
Under what circumstances can an edge with cost $$$w$$$ be added between vertex $$$u$$$ and vertex $$$v$$$ in a new graph?
Consider divide and conquer.
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int S=300005;
int n,m,k;
vector<pair<int,int> > vec[S];
int fa[S],hei[S],pt[S],fa2[S];
int top,*pot[S*3],val[S*3];
long long ans;
int fnd(int x){return fa[x]==x?x:fnd(fa[x]);}
int fnd2(int x){return fa2[x]==x?x:fa2[x]=fnd2(fa2[x]);}
inline void push(int &x){pot[++top]=&x,val[top]=x;}
inline void pop(){*pot[top]=val[top],top--;}
inline void merge(int x,int y,int w)
{
int rx=fnd(x),ry=fnd(y);
if(rx==ry) return;
int px=pt[rx],py=pt[ry];
if(px!=0&&py!=0)
{
int rx=fnd2(px),ry=fnd2(py);
if(rx!=ry) ans+=w,fa2[rx]=fa2[ry];
}
if(hei[rx]>hei[ry]) swap(rx,ry);
push(hei[ry]),hei[ry]=max(hei[ry],hei[rx]+1);
push(pt[ry]),pt[ry]=max(pt[ry],pt[rx]);
push(fa[rx]),fa[rx]=ry;
}
void doit(int l,int r,int w)
{
if(l==r) return;
int tp=top;
int mid=l+r>>1;
for(int i=r;i>=mid+1;i--)
for(auto t:vec[i]) merge(t.first,t.second,w);
doit(l,mid,w);
while(top>tp) pop();
for(int i=l;i<=mid;i++)
{
if(!vec[i].empty()&&w==i) w++;
for(auto t:vec[i]) merge(t.first,t.second,w);
}
doit(mid+1,r,w);
while(top>tp) pop();
}
inline void slove()
{
cin>>n>>m>>k;
for(int i=0;i<=m;i++) vec[i].clear();
for(int i=1,x,y,w;i<=m;i++) cin>>x>>y>>w,vec[w].emplace_back(x,y);
vector<int> tmp;
for(int i=1,x;i<=k;i++) cin>>x,tmp.push_back(x);
sort(tmp.begin(),tmp.end());
tmp.erase(unique(tmp.begin(),tmp.end()),tmp.end());
k=tmp.size();
for(int i=1;i<=n;i++) pt[i]=0;
for(int i=0;i<k;i++) pt[tmp[i]]=i+1;
for(int i=1;i<=n;i++) fa[i]=i,hei[i]=1;
for(int i=1;i<=k;i++) fa2[i]=i;
ans=0;
doit(0,m,0);
for(int i=1;i<=k;i++) if(fnd2(i)!=fnd2(1)) return cout<<"-1\n",void();
cout<<ans<<'\n';
}
int main()
{
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int T;
cin>>T;
while(T-->0) slove();
return 0;
}
Author: Lyz09 Developer: Z-301
What is the value of a path that passes through the centroid of a tree?
What is the value of a path that does not pass through the centroid of a tree?
This is a convolution problem. Enumerate only the terms in the polynomial with non-zero coefficients and prove that the time complexity is correct.
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
typedef vector<int> vi;
class edge{
public:
edge(int x, int y, int z, int zz){v = x, w = y, c = z, nxt = zz;}
int v, w, c, nxt;
};
class graph{
private:
vector<int> head;vector<edge> e;
public:
void init(int n){head.clear(), e.clear();for (int i = 0;i <= n;i ++) head.emplace_back(-1);}
graph(){}graph(int n){init(n);}
inline int addedge(int u, int v, int w = 0, int c = 0){e.emplace_back(v, w, c, head[u]), head[u] = e.size() - 1;return e.size() - 1;}
inline int add2edge(int u, int v, int w = 0){int tmp = addedge(u, v, w);addedge(v, u, w);return tmp;}
inline int addfedge(int u, int v, int w, int c = 0){int tmp = addedge(u, v, w, c);addedge(v, u, 0, -c);return tmp;}
inline int& h(int u){return head[u];}
inline edge& operator[](int i){return e[i];}
}G;
const int N = 100005;ll ans[N];vi a[N];vector<ll> b[N];
int t, n, al, mns, rt, sz[N], cnt[N];
void dfs(int u, int fa){int mx = 0;sz[u] = 1;
for (int i = G.h(u);i != -1;i = G[i].nxt){
int v = G[i].v;if (v == fa) continue;
dfs(v, u), sz[u] += sz[v], mx = max(mx, sz[v]);
}mx = max(mx, al - sz[u]);
if (mx < mns) rt = u, mns = mx;
}
void dfs1(int u, int fa, int mx, int rt){
a[rt].push_back(max(mx, sz[u]));
for (int i = G.h(u);i != -1;i = G[i].nxt){
int v = G[i].v;if (v == fa) continue;
dfs1(v, u, max(mx, sz[u] - sz[v]), rt);
}
}
void calc(vi& a, vector<ll>& s, vi& b, int o){
int p = upper_bound(a.begin(), a.end(), o) - a.begin();
for (int i = 0, j;i < b.size();i ++){
j = upper_bound(a.begin(), a.end(), b[i]) - a.begin();
if (b[i] > o) ans[o] -= j, ans[b[i]] += j;j = max(j, p);
if (j < a.size()) ans[o] -= a.size() - j, s[j] ++;
}
}
void dfs2(int u, int fa){vi vc;
for (int i = G.h(u);i != -1;i = G[i].nxt){
int v = G[i].v, w = sz[v];if (v == fa) continue;
ans[n - w - w] += 1ll * cnt[w] * w, cnt[w] += w, vc.push_back(w);
}sort(vc.begin(), vc.end()), vc.erase(unique(vc.begin(), vc.end()), vc.end());
for (int x : vc) for (int y : vc) if (x < y)
ans[n - x - y] += 1ll * cnt[x] * cnt[y];
for (int v : vc) ans[n - v] += (u != rt) * cnt[v], cnt[v] = 0;
for (int i = G.h(u);i != -1;i = G[i].nxt){
int v = G[i].v;if (v != fa) dfs2(v, u);}
}
void solve(int u){vi to;
for (int i = G.h(u);i != -1;i = G[i].nxt){
int v = G[i].v;to.push_back(v), dfs1(v, u, 0, v);
sort(a[v].begin(), a[v].end()), b[v].resize(a[v].size(), 0);
}
for (int x : to) if (sz[x] * 3 >= n) for (int y : to) if (x < y || sz[y] * 3 < n) calc(a[x], b[x], a[y], n - sz[x] - sz[y]);
for (int v : to){ll ls = 0;
for (ll& x : b[v]) ls = x += ls;
for (int i = 0;i < a[v].size();i ++)
ans[max(a[v][i], n - sz[v])] ++,
ans[a[v][i]] += b[v][i];a[v].clear(), b[v].clear();
}dfs2(rt, 0);
}
int main(){scanf("%d", &t);
while (t --){scanf("%d", &n), G.init(n);
for (int i = n - 1, u, v;i --;)
scanf("%d%d", &u, &v), G.add2edge(u, v);memset(ans, 0, n + 1 << 3);
al = n, mns = N, dfs(1, 0), dfs(rt, 0), solve(rt), ans[n] += n;
for (int i = 1;i <= n;i ++) printf("%lld ", ans[i]);putchar('\n');
}
}
Author: CutieSmileHaruka
You are given an array $$$a$$$. How to count the number of arrays $$$b$$$ that satisfy $$$f(b) = a$$$ and $$$ \forall 1 \le i \le n, b_i \le r_i $$$.?
You are given an array $$$a$$$. How to count the number of arrays $$$b$$$ that satisfy $$$f(f(b)) = a$$$ and $$$ \forall 1 \le i \le n, b_i \le r_i $$$.?
How many arrays $$$a$$$ satisfy there exists an array $$$b$$$ such that $$$f(f(b)) = a$$$?
// 全身全霊!MORE MORE JUMP!!
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
#define mod 998244353
using namespace std;
typedef __int128_t lll;
template<typename T, const int M>
struct BHasher{inline int operator()(T x){return x % M;}};
template<typename T1, typename T2, int M, typename Hsr = BHasher<T1, M>>
struct HashMap{
struct node{int nx;T1 ky;T2 vl;};
int h[M];vector<node> nd;Hsr hsh;
HashMap(){memset(h, -1, sizeof(h));}
void clear(){memset(h, -1, sizeof(h)), nd.clear();}
inline bool find(T1 k){int p = hsh(k);
for (int i = h[p];i != -1;i = nd[i].nx)
if (nd[i].ky == k) return 1;return 0;
}
inline T2& operator[](T1 k){int p = hsh(k);
for (int i = h[p];i != -1;i = nd[i].nx)
if (nd[i].ky == k) return nd[i].vl;
nd.push_back((node){h[p], k, T2()});
return nd[h[p] = nd.size() - 1].vl;
}
};
const int N = 55, K = 1005, M = 1296000;HashMap<lll, int, 1919839> id;
int t, n, m, k, c, a[N], fa[M], to[M][N], C[N][N], f[M], ans[K], rt, cnt;
unsigned char b[M][N], bb[N], ps[M][N], sk[N], tmp[N], sm[M], ct[M], dep[M];
void dfs(int p, int sm){
if (p > n){m ++;
memcpy(ps[m], sk, sizeof(sk));
memcpy(b[m], bb, sizeof(bb));
return;
}
for (int x = 0;x <= n && sm <= n;x ++, sm += p){
if (x) sk[++ c] = p;
bb[p] = x, dfs(p + 1, sm);
if (x) sk[c --] = 0;
}
}
inline lll hsh(unsigned char* A){lll st = 0;
for (int i = 1;i <= n;i ++)
st <<= 1, st |= 1, st <<= A[i];return st;
}
inline unsigned char gdep(int x){return dep[x] ? dep[x] : dep[x] = gdep(fa[x]) + 1;}
inline void add(int& x, int y){x += y;if (x >= mod) x -= mod;}
int main(){scanf("%d", &t), n = N - 5;
for (int i = 0;i <= n;i ++){C[i][0] = 1;
for (int j = 1;j <= i;j ++) C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;}
while (t --){scanf("%d%d", &n, &k), m = cnt = 0, dfs(1, 0);
memset(dep, 0, m + 1 << 1), memset(f, 0, m + 1 << 2), memset(ans, 0, k + 1 << 2);
for (int i = 1;i <= n;i ++) scanf("%d", &a[i]);
for (int i = 1;i <= m;i ++){
lll st = hsh(b[i]);id[st] = i;
for (int j = n, p = -1;j >= 1;j --){
p += b[i][j] + 1;if (b[i][j])
to[i][j] = id[((st >> p) << p - 1) | (st & ((lll)1 << p) - 1)];
}
}
for (int i = 1;i <= m;i ++){
memset(tmp, 0, sizeof(tmp)), sm[i] = ct[i] = 0;
for (int j = 1;j <= n;j ++)
tmp[b[i][j]] ++, sm[i] += j * b[i][j], ct[i] += b[i][j];
if (sm[i] == 1) rt = i;
fa[i] = id[hsh(tmp)];
}f[1] = dep[1] = dep[rt] = 1;
for (int i = n, ss = 0;i >= 1;i --){
for (int o = 1;o <= n;o ++) ss += a[o] == i;
for (int j = m;j >= 1;j --)
if (ct[j] <= n - i + 1 && sm[j] <= ss)
for (int k = 1, x, now;ps[j][k];k ++)
if (now = f[to[j][x = ps[j][k]]])
f[j] = (f[j] + 1ll * now * C[ss - sm[j] + x][x]) % mod;
}
for (int i = 2;i <= m;i ++) add(ans[gdep(i) + 2], f[i]);
for (int i = 1;i <= n;i ++) cnt += a[i] > 0;
add(ans[3], mod - cnt), add(ans[2], cnt - (a[1] > 0)), add(ans[1], 1 + (a[1] > 0));
for (int i = 1;i <= k;i ++) printf("%d ", ans[i]);putchar('\n');
}
}








Auto comment: topic has been updated by CutieSmileHaruka (previous revision, new revision, compare).
yet another implementation round
In C i got to the point where median of segments = median of fulll array if it exists
the trick lies in where we can compute if median of a segment = M using the comparisons which are precomputed once we fix the median
Learned something new.
I created video editorial for C. Median Partition.
I also created video editorial for D. Permutation Construction
I also created video editorial for easy version of F. Building Tree.
I also created video editorial for the easy version of G. Statistics on Tree.
Screencast (with commentary) of me struggling, but managing to solve A and B.
my apparach for C
First, I precomputed the median for all prefix subarrays of odd size. Then for each recursive call, I enforced that prefix median onto the rest
Cool problem E.
Subject: Weak Test Data Report: Inefficient DP Solution Passes Time Limit in [Insert Problem Letter] — Nanatsukaze — Save Our Sound https://codeforces.me/contest/2222/problem/A
To the Problem Setter / Contest Coordinators,
I am writing to report a case of weak test data for the problem Nanatsukaze — Save Our Sound.An incredibly inefficient, Unbounded Knapsack Dynamic Programming solution is currently passing all system tests and being Accepted. The code has a worst-case time complexity that should clearly result in a Time Limit Exceeded (TLE), but it passes because the system tests are missing a specific "worst-case" scenario where the answer is "Yes" and $$$N$$$ is maximized.The Flaw in the Accepted CodeThe code attempts to check every possible score from $$$0$$$ to $$$100 \cdot n$$$ by running an unbounded knapsack DP for each target score independently.Furthermore, the code dynamically allocates a vector inside the DP function during every single iteration of the loop.
Here is the exact submission that gets accepted: https://codeforces.me/contest/2222/submission/372573074
Why it should TLE (Complexity Analysis)If the array does not contain 100 (meaning the answer is "No"), the DP quickly fails on target = 1 and breaks the loop. The execution time is negligible.However, if the array does contain 100 (meaning the answer is "Yes"), the DP loop never breaks early. It must check every number up to $$$100 \cdot N$$$.For a maxed-out test case where $$$T = 100$$$, $$$N = 10$$$, and all $$$a_i = 100$$$:The outer loop runs $$$100 \times 10 = 1,000$$$ times per testcase.can() is called $$$1,000$$$ times, allocating a vector on the heap every single time.The nested loops inside can() result in roughly $$$10,000,000$$$ operations per test case.For $$$T=100$$$, this results in $$$\approx 10^9$$$ operations and 100,000 dynamic memory allocations, which takes roughly 5 to 10 seconds locally and heavily exceeds standard time limits.
The Missing Worst-Case Test DataTo break this code, the system tests need a file filled with maximum values where the answer is "Yes".
100 10 100 100 100 100 100 100 100 100 100 100 10 100 100 100 100 100 100 100 100 100 100 ... (repeated 100 times total)
I find the explanation for problem C not very understandable. Can you explain in more detail how to compute dp[i] exactly.
let dp[i] = max number of partitions of the subarray [0..i] into odd length segments with median = full median. dp[i] = max(dp[j]+1) over all j where j<i, the subarray [j+1..i] has odd length, and the median of [j+1..i] = full median. if all those conditions are satisfied, its a valid partition. you can check for the 3rd condition by checking if num(elements <= median) <= (i-j+1)//2 and num(elements >= median) <= (i-j+1)//2, you can use prefix sums to precompute these counts
My approach for C was: 1. Start walking through the array, if the median so far is as desired AND it is possible to split the rest of the array in some way to fulfill the condition, then I should cut off the array so far, sum+=1, start over with the shorter array. 2. My approach to finding out whether or not the rest of the array was splittable at all was: if the rest of the array is odd length, just check if the array as whole is valid (has correct median), if the rest of the array is even length, check for every index where we would split it into two odd-length arrays if both of these odd-length arrays are valid. If that is the case at no index, I figured, it wouldn't be possible at all.
This survived the first 3 test cases, but failed on pretest 4. I am not even quite sure which assumption is incorrect (1. or 2.). Does someone know what is wrong with my approach?
I had a very similar approach, and I too am stuck at test case 4. If you find out the reason your submission failed, would you kindly let me know as well?
Haven't really had much time to think about it but I wrote a test generator and used the solution's code on a little grader script:
The explanation is actually quite obvious. There is clearly no difference between numbers that are both below or both above the median. So the above input is:
If you cut off the first three elements, as
- . .has the correct median, you are missing the oppotunity to include the next two+which would be benefitial, because in the section after that, there are more-s than+s. With less+, you can cut off the next group earlier. The two partitions of my idea and the correct one are:C can be solved without the fact that the median of each subarray is also the median of the whole sequence. Let $$$f(l, r)$$$ be the median of $$$a_l, a_{l+1}, \dots, a_r$$$. We fix the median as $$$x$$$, and let $$$dp_i$$$ be the number of subarrays when each one has median $$$x$$$. The idea is we only iterate through all $$$j$$$ such that $$$f(j, i)=x$$$, meaning across all $$$x$$$ there will be $$$O(n^2)$$$ transitions. I'm just unsure if $$$f$$$ can be computed faster than $$$O(n^2 \log n)$$$.
Yeah I had a similar idea, did anyone check for tle
Yes, it is possible to compute the medians of each subarrays in $$$O(n^2)$$$. Like in the $$$O(n^2 \ln n)$$$ solution, for each start $$$l$$$, we move $$$r$$$ to the right.
Let's maintain a frequency array, a pointer to the current median, and the number of elements strictly less than that median. When add new elements median moves by at most one position.
So our goal effective find nearest non-zero value in frequency array (to move median). A naive scan require $$$O(n^3)$$$. So, for each element we need link to nearest non-zero neighbour – essentially maintaining a sorted linked list.
Last, we need to find position to insert new value into this linked list. This can be precomputed: we looking for element which is closest to new value $$$a[r]$$$ among all elements in segment $$$[a_l, a_{l+1}, ..., a_{r-1}]$$$. The new value $$$a[r]$$$ will be "attached" to that element.
submission: 372654561
This still passes without the linked list, just naively scanning over the array. I didn't consider zeroes during the contest and only realised after the contest was over that it should TLE.
Submission: 372487900
I was able to force inner while loops in your solution to do $$$3.77 \cdot 10^9$$$ iterations but it still passed the test in $$$1.67s$$$ :(
https://codeforces.me/contest/2222/hacks/1172057/test
So it looks like even though your solution is $$$O(n^3)$$$, the constant behind it is just too small for it to be hacked.
UPD: rafaeLL found a simplier and better test on which your solution makes $$$5.21 \cdot 10^9$$$ operations and gets TLE :)
https://codeforces.me/contest/2222/hacks/1172059/test
i used a similar but a bit different method on E. To track the value of c i just constructed it bit by bit from n-1 to 0th bit.
372518426
I think C can be solved in O(nlogn).
Let m denote the median of the original sequence. Make a new array B s.t. Bi=-1 if Ai < m, Bi=0 if Ai=m, and Bi=1 if Ai>m Then a subarray from l to r will have m as its median if the sum of Bi from l to r is equal to 0. Or, put in another way, if we define prefB as the prefix sum of B, prefB[r] = prefB[l-1]
We can define dp[i] as the maximum number of segments constructible if we only consider prefix ending at i. Then: dp[i] = max(dp[j] + 1) for all j s.t. prefB[i]=prefB[j-1] and j has the same parity with i
We need 2 maps: one that saves dp[i] for odd i and one for even i.
The answer will be dp[n]
Nevermind, B can have nonzero sum yet have its median=m. Example: m=3 with the array 1 3 3
I think the correct condition is the subarray must have m in it and the sum has to be = 1. Bi is then defined with Bi=-1 if Ai<m else Bi=1
Edit: this does not work either T-T
That was my first solution before I realised this mistake
I don’t get why my solution for C got AC
it should’ve been TLECode: 372534662
For the E bonus: In the situarion where
0 <= c < 2^n - 1isn't it impossible? Because then we havef(x) = xfor both xor and or operations if c=0.fast editorial but i did not like the contest.
C is solvable in O(nlog^2n) with CDQ Div n Conquer
Denote m as the median of the original sequence. Make 2 new sequences
PandQ.Pis defined with:P[i] = P[i-1] + (A[i] >= m ? 1 : -1)Similarly
Qis defined withQ[i] = Q[i-1] + (A[i] > m ? 1 : -1)Then a subarray from l to r has median = m if:
P[r] - P[l-1] >= 1,Q[r] - Q[l-1] <= -1,r and l has the same parityThis is a version of 3d partial order problem that can be solved using CDQ DnC. However, we have an additional condition that r and l has the same parity. To handle this we use 2 different fenwick trees, one for odd indices and one for even.
Code
i didn't quite understand the editorial for problem D, can anyone explain me the proof for this part?
Consider maximizing the beauty of the permutation p. The ideal situation is that for all (i,j) where bj>bi and i<j, pi>pj is satisfied, and for all (i,j) where bj<bi and i<j , pi<pj is satisfied. ??
To maximize the beauty, you want your construction to add only subarrays that have positve sum, thus if you are on index $$$i$$$ and you have prefix sum $$$b_i$$$ every $$$j$$$ $$$(j \lt i)$$$ that $$$b_j \lt b_i$$$ will give you positive score to your answer and the opposite goes to $$$b_j \gt b_i$$$
Let $$$Pref_i = \sum_{k=1}^{i-1}$$$. Then $$$\sum_{k=i}^{j-1} a_k = Pref_j-Pref_i$$$. Now we will focus on contribution of $$$Pref_x$$$. The final answer will contain $$$\cdot Pref_x$$$ for each inversion $$$(i,x)$$$ (let $$$l_x$$$ be count of such inversions), and $$$-Pref_x$$$ for each inversion $$$(x,i)$$$ (similarly denote their count by r_x). Suppose there is $$$p_x$$$ on position $$$x$$$. Note, that if there are $$$r_x$$$ numbers smaller than $$$p_x$$$ on the right of position $$$x$$$, then there are $$$p_x-1 - r_x$$$ numbers smaller than $$$p_x$$$ on the left of position $$$x$$$, so there are $$$(x-1) - (p_x-1 - r_x)=x-p_x+r_x = l$$$ numbers larger than $$$p_x$$$ on the left of position $$$x$$$. So $$$\sum_{k=i}^{j-1} a_k = \sum_x l_x\cdot Pref_x - r_x \cdot Pref_x = \sum_x(x-p_x+r)\cdot Pref_x -r\cdot Pref_x = \sum_x (x-p_x)\cdot Pref_x = \sum_x x\cdot Pref_x - \sum_x p_x\cdot Pref_x$$$. So $$$l_x, r_x$$$ canceled out meaning the contribution from each position depends only on number we place on this position. Now the firt sum is constant, and to minimalize second sum we can use rearrangement inequality. Thats why we need to pair largest numbers from permutation with smallest $$$Pref_x$$$.
I used $$$a=2^n-1$$$ in the solution of Problem E. You can check out my code here 372655599, if it concerns you.
Note: Added some comments to make it easier to understand.
can someone tell me when we are creating a new graph,
and two nodes have same color,
what is the time required to connect to those nodes ?
The time required is 0. There was an announcement during the contest clarifying that $$$dis(u, u) = 0$$$ because it's the MEX of an empty set.
Nice problem E!
On H it is kind of funny that $$$g(a)$$$ is deceptively small (at most $$$10$$$, proving that is kinda cool to build intuition) but it isn't useful at all to solve the problem.
全身全霊!MORE MORE JUMP!!
It's Nanatsukaze Round!
Here is a method to solve Problem C within a complexity of $$$O(n\log^2n)$$$。 First, note that the median of each partition is the same and fixed, which we denote as $$$x$$$. For other numbers, we only care about whether they are greater than or less than $$$x$$$.
Let $$$f_i$$$ denote the maximum number of segments into which prefix $$$i$$$ can be divided. $$$f_j$$$ can transition to $$$f_i$$$ if and only if the length of the interval $$$[j+1,i]$$$ is odd, and the number of numbers in the interval that are greater/smaller than $$$x$$$ is less than half the length of the interval. Now we have achieved a time complexity of $$$O(n^2)$$$.
Let $$$s_i, t_i$$$ denote the number of numbers greater/smaller than $$$x$$$ respectively for prefix $$$i$$$. The condition can be written as:
Without the restriction of parity, this is a well-known three-position partial order problem, which can be solved using the divide-and-conquer approach.
Taking into account the parity constraints, we consider maintaining two data structures to represent odd and even numbers during the divide-and-conquer process. During the merging process, only transfers between different sets of data structures are allowed. Thus, we have solved this problem with a time complexity of $$$O(n\log^2 n)$$$.
okak
Can anyone please explain, why the solution explained in problem D maximizes the answer? Because even if the value we add from every inversion [i; j] is not negative, how can we know that this guarantees biggest outcome?
hi
the maximum value we can achieve is the sum of all intervals with a positive sum without the last element [as the last element can never be included ]
there can at max be n*(n -1)/2 pairs of positive sum sub arrays (and inversions)and we can graph them and we can choose weather to add a inversion (i j) yes or no.
so for each pair of indexes we choose to add them if they are positive so max answer will be sum of all such pairs.
you can create a directed acylic graph if you add an edge between i and j is sum between them is positive and when you run top sort on this you will get a array (topo) such that the value of ans[topo[i]] > ans[topo[j]] if i < j.
link to code
here is a submission i made with the idea of writing a divide and conquer methord like merge sort. although final code uses sorting as sort function is an inbuilt merge sort of a kind .
i am thinking of another version using a segtree where we build a chain (linked list but with faster ability to swap and insert elements ) whern the ith element is inserted before the maximum right most prefix val before i -1 <= to it. although i am struggling to formulate this approach