CodeforcesRound1005(Div.2)(A-D)
- 手机
- 2025-09-05 01:15:02

题目链接:Dashboard - Codeforces Round 1005 (Div. 2) - Codeforces
A. Brogramming Contest 思路每次把后缀1...10...0放到t里面再把0...0放回s,这样重复
代码 void solve(){ int n; cin>>n; string s; cin>>s; int cnt=0; bool f=false; for(int i=0;i<n;i++){ if(s[i]=='1'){ if(!f) cnt++; f=true; } if(s[i]=='0'){ if(f) cnt++; f=false; } } cout<<cnt<<"\n"; } signed main() { vcoistnt cout<<fixed<<setprecision(2); int _=1; cin>>_; while(_--) solve(); return 0; } B. Variety is Discouraged 思路可以发现a的最大得分就是n-cnt,(n表示数组a的长度,cnt是只出现一次的数量),那么我们发现如果移除一个只出现一次的数是不会改变得分的,移除出现多次的数会使得得分变小,这么这题就可以转换成寻找只包含出现一次数的最大子数组
代码 #include<bits/stdc++.h> using namespace std; #define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); #define int long long #define ull unsigned long long #define bit __builtin_popcount #define lowbit(x) ((x)&-(x)) #define vi vector<int> #define vb vector<bool> typedef pair<int,int> pll; const int N=2e5+10; const int inf=1e18; const int mod=998244353; void solve(){ int n; cin>>n; vi a(n+10); map<int,int> mp; for(int i=1;i<=n;i++){ cin>>a[i]; mp[a[i]]++; } int i=1; int l=-1,r=-1; int mx=0; while(i<=n){ if(mp[a[i]]==1){ int x=i; int st=i; while(mp[a[x]]==1) x++; int ed=x-1; if(x-i>mx){ mx=x-i; l=st; r=ed; } i=x; }else{ i++; } } if(l==-1){ cout<<"0\n"; }else{ cout<<l<<" "<<r<<"\n"; } } signed main() { vcoistnt cout<<fixed<<setprecision(2); int _=1; cin>>_; while(_--) solve(); return 0; } C. Remove the Ends 思路我们发现选择一个负数会把后面的数全删掉,那么我们贪心地从后往前选负数,选择一个正数会把前面的数删掉,我们贪心地从前往后选正数。如果我们选择了一个负数,那么这个负数之后的正数是不可选的;
那么我们遍历一遍 正数的前缀和+负数的后缀和 取最大值即是答案
代码 #include<bits/stdc++.h> using namespace std; #define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); #define int long long #define ull unsigned long long #define bit __builtin_popcount #define lowbit(x) ((x)&-(x)) #define vi vector<int> #define vb vector<bool> typedef pair<int,int> pll; const int N=2e5+10; const int inf=1e18; const int mod=998244353; void solve(){ int n; cin>>n; vi a(n+10); for(int i=1;i<=n;i++){ cin>>a[i]; } vi p(n+10,0); vi suf(n+10,0); for(int i=1;i<=n;i++){ if(a[i]>0) p[i]=p[i-1]+a[i]; else p[i]=p[i-1]; } for(int i=n;i>=1;i--){ if(a[i]<0) suf[i]=suf[i+1]-a[i]; else suf[i]=suf[i+1]; } int ans=0; for(int i=1;i<=n;i++){ ans=max(ans,p[i]+suf[i]); } cout<<ans<<"\n"; } signed main() { vcoistnt cout<<fixed<<setprecision(2); int _=1; cin>>_; while(_--) solve(); return 0; } D. Eating 思路首先这题要x>=w[i]才能吃掉,我们转换一下,根据异或的性质我们可以用suf[i]表示后缀异或和,即只有那么我们才能够把w[i-1]给吃掉,从后往前找到第一个不满足的即可;
发现如果我们直接遍历的话会超时,那么我们接下来需要解决如何优化
如果x>=y,那么二进制下x的最高位1的位置>=y的最高位1,且只有x的最高位1=y的最高位1时之后x的最高位1的位置才会改变
那么我们便可把问题转化为每次从后往前找到第一个最高位1的位置>=当前x的最高位,如果能够吃掉就更新x的最高位,否则结束搜索;具体查找可以用线段树实现,细节看代码。
代码 #include<bits/stdc++.h> using namespace std; #define vcoistnt ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); #define int long long #define vi vector<int> #define vb vector<bool> typedef pair<int,int> pll; const int N=2e5+10; const int inf=1e18; const int mod=998244353; int get(int x){ //得到二进制下x最高位1的位置 if(x==0) return -1; return 31-__builtin_clz(x); } struct SegmentTree { int n; vector<int> mx; SegmentTree(const vector<int>& a) { n = a.size(); mx.resize(4 * n); build(0, 0, n - 1, a); } void build(int id, int l, int r, const vector<int>& a) { if (l == r) { mx[id] = a[l]; return; } int mid = (l + r) / 2; build(2*id+1, l, mid, a); build(2*id+2, mid+1, r, a); mx[id] = max(mx[2*id+1], mx[2*id+2]); } int query(int id, int l, int r, int start, int x) { if (r < start || mx[id] < x) return -1; if (l == r) return l; int mid = (l + r) / 2; int L = query(2*id+1, l, mid, start, x); if (L != -1) return L; return query(2*id+2, mid+1, r, start, x); } int find(int start, int x) { return query(0, 0, n-1, start, x); } }; void solve(){ int n,q; cin>>n>>q; vi w(n); for(int &x:w) cin>>x; vi rev(n); //将w倒转方便后续操作 vi h(n); //最高位1位置 int mxb=-1; //最大最高位 for(int i=0;i<n;i++){ rev[i]=w[n-1-i]; h[i]=get(rev[i]); mxb=max(mxb,h[i]); } vi pre(n+1,0); //异或前缀 for(int i=0;i<n;i++){ pre[i+1]=pre[i]^rev[i]; } SegmentTree st(h); while(q--){ int x;cin>>x; int curb=get(x); if(curb>mxb){ cout<<n<<" ";continue; } int cnt=0; int pos=0; while(pos<n){ int i=st.find(pos,curb); //找到第一个最高位1>=x的位置 if(i==-1){ cnt+=(n-pos); break; } cnt+=(i-pos); x^=(pre[i]^pre[pos]); curb=get(x); pos=i; if(h[pos]>curb){ break; } if(x>=rev[pos]){ cnt++; x^=rev[pos]; curb=get(x); pos++; }else{ break; } } cout<<cnt<<" "; }cout<<"\n"; } signed main() { vcoistnt cout<<fixed<<setprecision(2); int _=1; cin>>_; while(_--) solve(); return 0; }CodeforcesRound1005(Div.2)(A-D)由讯客互联手机栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“CodeforcesRound1005(Div.2)(A-D)”