A
记录每个数出现的次数\(a\) ,如果存在\(a\) 为奇数,那么输出YES。否则最后输出NO。
#include <bits/stdc++.h> #define lowbit(x) x&(-x) const int MAXN=2e5 +10 ;const int mod=998244353 ;using namespace std;using ll=long long ;void solve () ;int main () { int t=1 ; cin>>t; while (t--) { solve (); } } int mp[MAXN];void solve () { int n; cin>>n; memset (mp,0 ,sizeof (mp)); vector<int > a (n+1 ,0 ) ; for (int i=1 ;i<=n;i++) { cin>>a[i]; mp[a[i]]++; } for (int i=1 ;i<=n;i++) { if (mp[a[i]]%2 ) { cout<<"YES\n" ; return ; } } cout<<"NO\n" ; }
B
不难想到在\(x\) 的右边所有数的总和小于0,而在\(y\) 的左边所有数的总和小于0,所以先初始化为1,然后在\(x+1,x+3······\) 这样交替进行构造。\(y-1,y-3\) 也是如此。
#include <bits/stdc++.h> #define lowbit(x) x&(-x) const int MAXN=2e5 +10 ;const int mod=998244353 ;using namespace std;using ll=long long ;void solve () ;int main () { int t=1 ; cin>>t; while (t--) { solve (); } } int a[MAXN];void solve () { int n,x,y; cin>>n>>x>>y; for (int i=1 ;i<=n;i++) { a[i]=1 ; } for (int i=x+1 ;i<=n;i+=2 ) { a[i]=-1 ; } for (int j=y-1 ;j>=1 ;j-=2 ) { a[j]=-1 ; } for (int i=1 ;i<=n;i++) { cout<<a[i]<<" " ; } cout<<"\n" ; }
C
对原序列求一次MAD操作得到数组\(b\) ,不难发现:\(b\) 数组是一个单调递增的数组,每次操作后是对\(b\) 进行向右平移操作,前面用0补充。需要注意的是:
如果同一个数字在\(b\) 中出现多次,那么做一次MAD运算后是右移。
如果是出现一次的话,就用前面的进行填充即可,再计算上贡献。
#include <bits/stdc++.h> #define lowbit(x) x&(-x) const int MAXN=2e5 +10 ;const int mod=998244353 ;using namespace std;using ll=long long ;void solve () ;int main () { int t=1 ; cin>>t; while (t--) { solve (); } } ll a[MAXN]; ll b[MAXN]; ll mp[MAXN]; map<ll,int > m; void solve () { int n; cin>>n; ll maxn=0 ; m.clear (); for (int i=1 ;i<=n;i++) { mp[i]=b[i]=0 ; } ll sum=0 ; ll tmp=0 ; for (int i=1 ;i<=n;i++) { cin>>a[i]; sum+=a[i]; if (mp[a[i]]) { b[i]=max (a[i],maxn); maxn=max (b[i],maxn); } else { mp[a[i]]++; b[i]=b[i-1 ]; } } for (int i=1 ;i<=n;i++) { m[b[i]]++; } for (int i=1 ;i<=n;i++) { if (m[b[i]]>=2 ) { sum+=b[i]*(n-i+1 ); } else { sum+=b[i]+b[i-1 ]*(n-i); b[i]=b[i-1 ]; } } cout<<sum<<"\n" ; }
另外的方法:实际上模拟两次即可(模拟完两次后,出现一次的元素就消失了,直接计算出现多次的情况即可)。
#include <bits/stdc++.h> using u32 = unsigned ;using i64 = long long ;using u64 = unsigned long long ;void solve () { int n; std::cin >> n; std::vector<int > a (n) ; for (int i = 0 ; i < n; i++) { std::cin >> a[i]; } i64 ans = 0 ; for (int t = 0 ; t < 2 ; t++) { std::vector<int > vis (n + 1 ) ; int mx = 0 ; for (auto &x : a) { ans += x; if (vis[x]) { mx = std::max (mx, x); } vis[x] = 1 ; x = mx; } } for (int i = 0 ; i < n; i++) { ans += 1LL * (n - i) * a[i]; } std::cout << ans << "\n" ; } int main () { std::ios::sync_with_stdio (false ); std::cin.tie (nullptr ); int t; std::cin >> t; while (t--) { solve (); } return 0 ; }
D
后来补的题目:应该是按照题目进行模拟吧。
关键是样例二,可以用方块进行跨行填补。代码细节比较多,不太好调。
最后需要留意的是用\(a[n]\) 特判一下。
#include <bits/stdc++.h> #define lowbit(x) x&(-x) const int MAXN=2e5 +10 ;const int mod=998244353 ;using namespace std;using ll=long long ;void solve () ;int main () { int t=1 ; cin>>t; while (t--) { solve (); } } int a[MAXN];void solve () { int n; cin>>n; for (int i=1 ;i<=n;i++) { cin>>a[i]; } int ans=0 ; for (int i=1 ;i<n;i++) { if (a[i]==0 ) continue ; else if (a[i]>2 ) { ans++; } else { if (a[i+1 ]<=2 ) { ans++; a[i+1 ]=0 ; } else if (a[i+1 ]<=4 && a[i+2 ]>2 && i+2 <=n) { ans+=2 ; a[i+1 ]=0 ; a[i+2 ]-=2 ; } else { ans++; } } } if (a[n]) ans++; cout<<ans<<"\n" ; }