A - Yet Another Tetris Problem
这题一开始看错题了啊啊啊啊啊
总的来说就是看所有 $a_i$ 的奇偶性相不相同就行......
#include <bits/stdc++.h> #define ll long long using namespace std; int n; int a[105]; int b[105][105]; int main() { int Test;cin>>Test; while(Test--) { cin>>n; int mx=0; for(int i=1;i<=n;++i)cin>>a[i]; int op=(a[1]&1); bool flag=1; for(int i=1;i<=n;++i) { if(op!=(a[i flag=0; } if(flag)puts("YES");else puts("NO"); } return 0; }
B - Yet Another Palindrome Problem
做法比较多,$O(n)$ 或者 $O(n^2)$ 的都可以。我用的 $O(n^2)$,直接枚举每个数,看这个数出现在最左边或者最右边的位置,不相邻就行。
#include <bits/stdc++.h> #define ll long long using namespace std; int n; int a[5005]; int main() { int Test;cin>>Test; while(Test--) { cin>>n; for(int i=1;i<=n;++i)cin>>a[i]; bool flag=0; for(int i=1;i<=n;++i) { int L=-1,R=-1; for(int j=1;j<=n;++j) { if(a[j]==i) { L=j; break; } } for(int j=n;j;--j) { if(a[j]==i) { R=j; break; } } if(R-L>=2) { flag=1;break; } } if(flag)puts("YES"); else puts("NO"); } return 0; }
C - Frog Jumps
直接统计最长的连续L就行,答案就是长度+1
#include <bits/stdc++.h> #define ll long long using namespace std; int n; char s[200050]; int main() { int Test;cin>>Test; while(Test--) { scanf( s[n+1]=s[n+2]=0; int ans=0,tmp=0; for(int i=1;i<=n+1;++i) { if(s[i]=='L')tmp++; else ans=max(ans,tmp),tmp=0; } cout<<ans+1<<'\n'; } return 0; }
D - Pair of Topics
写了个离散化+BIT......cjj写了个Treap2333
#include <bits/stdc++.h> #define ll long long using namespace std; int n; ll a[200050],b[200050]; ll ans; ll t[500050]; map <int,int> h; vector <ll> vec;int tot; inline int lowbit(int x){return x&(-x);} inline void change(int x,int val){while(x<=400000){t[x]+=val;x+=lowbit(x);}} inline int query(int x){int ret=0;while(x){ret+=t[x];x-=lowbit(x);}return ret;} int main() { cin>>n; for(int i=1;i<=n;++i)scanf( for(int i=1;i<=n;++i)scanf( for(int i=1;i<=n;++i) { vec.push_back(a[i]-b[i]); vec.push_back(b[i]-a[i]+1); } sort(vec.begin(),vec.end()); for(auto i:vec) { if(h[i])continue; h[i]=++tot; } for(int i=1;i<=n;++i) { ans+=query(h[a[i]-b[i]]); change(h[b[i]-a[i]+1],1); } cout<<ans<<endl; return 0; }
E - Sleeping Schedule
一道比较裸的dp...
设 $dp(i,j)$ 表示当前到第 $i$ 个数,总和对 $h$ 取模为 $j$ 的最大值,然后转移就两种情况取最大值。当 $j$ 在 $[l,r]$ 内时 $dp(i,j)++$ 。
#include <bits/stdc++.h> #define ll long long using namespace std; int n,h,l,r; int dp[2050][2050],f[2050][2050]; int ans; int a[2050]; int main() { scanf( for(int i=1;i<=n;++i)cin>>a[i]; f[1][0]=1; for(int i=1;i<=n+1;++i) { for(int j=0;j<h;++j) { if(f[i][j]==0)continue; if(i>1&&j<=r&&j>=l)dp[i][j]++; dp[i+1][(j+a[i] dp[i+1][(j+a[i]-1+h ans=max(ans,dp[i][j]); f[i+1][(j+a[i] } } cout<<ans<<endl; return 0; }
F - Maximum White Subtree
比较板的换根dp辣
我们将这棵树转成有根树,以 $1$ 为根
设 $f_u$ 表示 $u$ 从 $u$ 开始往下的 $u$ 的子树的最大值,$g_u$ 表示从 $u$ 往父亲走(不包括 $u$ )的最大值。
翻译一下就是把含 $u$ 的子树搞成两部分,一部分是 $u$ 的子树内(含 $u$ ),一部分是 $u$ 的子树外(不含 $u$ ),然后两次dfs,第一次统计 $f_u$,即 $f_u=\sum max(0,f_v)$ ,然后第二次dfs就统计 $g_u$,即 $g_u=max(f_{fa}+g_{fa}-max(f_u,0),0)$
最后答案就是 $f_u+g_u$。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N=200050; int f[N],g[N]; int n; struct edge { int v,nxt; }e[N<<1]; int a[N]; int head[N],ecnt; inline void ad(int u,int v) { e[++ecnt].v=v;e[ecnt].nxt=head[u]; head[u]=ecnt; } void dfs1(int u,int fa) { for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(v==fa)continue; dfs1(v,u); if(f[v]>=0)f[u]+=f[v]; } } void dfs2(int u,int fa) { if(fa)g[u]=max(f[fa]-f[u]*(f[u]>=0)+g[fa],0); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(v==fa)continue; dfs2(v,u); } } int main() { cin>>n; for(int i=1;i<=n;++i)scanf( for(int i=1;i<n;++i) { int x,y; scanf( ad(x,y);ad(y,x); } for(int i=1;i<=n;++i) { if(a[i]==0)f[i]=-1; else f[i]=1; } dfs1(1,0); dfs2(1,0); // for(int i=1;i<=n;++i) // { // printf("f // printf("g // } for(int i=1;i<=n;++i) { printf( } return 0; }
Comments NOTHING