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');
}
}



