海亮集训7.25周赛
A

签到
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=x*10+c-48;
x=(f ? -x : x);
return;
}
string s;
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
cin>>s;
if(s[0]=='0') cout<<s;
else{
cout<<s[0];
for(int i=1;i<s.size();i++){
cout<<(s[i]=='0' ? '1' : '0');
}
}
return 0;
}
//^o^
B

暴力
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=x*10+c-48;
x=(f ? -x : x);
return;
}
int l,r;
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
read(l),read(r);
int ans=0;
for(int i=r;i>=1;i--){
int j=r/i;
int a=i*j,b=i*(j-1);
if(a>=l&&a<=r&&b>=l&&b<=r){
ans=i;
break;
}
}
printf("%d",ans);
return 0;
}
//^o^
C

因为向右移一次时只会减少第a[n-1]和a[n]的异或值,增加a[1]和a[n]的异或值
所以预处理每个数作为开头时的异或和,然后再询问过程中维护一个开头即可
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
void read(LL& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=x*10+c-48;
x=(f ? -x : x);
return;
}
LL a[maxn];
LL ans[maxn];
LL n,q;
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
read(n),read(q);
for(int i=1;i<=n;i++){
read(a[i]);
if(i>1) ans[1]+=a[i]^a[i-1];
}
for(int i=1;i<n;i++){
int j=n-i+1;
ans[i+1]=ans[i]-(a[j]^a[j-1])+(a[j]^a[j%n+1]);
}
int st=1;
printf("%lld ",ans[1]);
LL x;
while(q--){
read(x);
st=(st+x-1)%n+1;
printf("%lld ",ans[st]);
}
return 0;
}
//^o^
D

不可忽视的取模
由于只向2取模,可以发现,一个串比另一个串若多上了偶数个1(可以为0个),其不相同个数肯定为偶数,即向2取模为零
用前缀和维护区间内1的数量即可
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=2e5+5;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=x*10+c-48;
x=(f ? -x : x);
return;
}
int n,m;
string sa,sb;
int a[maxn],b[maxn];
int main(){
//freopen("string2.in","r",stdin);
//freopen(".out","w",stdout);
read(n),read(m);
cin>>sa>>sb;
for(int i=1;i<=n;i++){
a[i]=a[i-1]+(sa[i-1]=='1' ? 1 : 0);
}
for(int i=1;i<=m;i++){
b[i]=b[i-1]+(sb[i-1]=='1' ? 1 : 0);
}
int q;
read(q);
int al,ar,bl,br;
while(q--){
read(al),read(ar),read(bl),read(br);
//cout<<a[ar]-a[al-1]<<' '<<b[br]-b[bl-1]<<endl;
if((a[ar]-a[al-1]-(b[br]-b[bl-1]))%2==0){
printf("0\n");
}
else{
printf("1\n");
}
}
return 0;
}
//^o^
E

我的解法居然比官解好,还抢到了最优解%%%%%%
可以证明数列只有两种情况:
峰,谷,峰,谷,峰,谷,峰,...
谷,峰,谷,峰,谷,峰,谷,...
我们尝试模拟着来修改,让前一个数去限制后一个数
分类讨论:
1.当前的数不满足前一个数的限制,此时必须对这个数进行修改,同时修改要兼顾到后面一个数
2.当前的数满足前一个数的限制,此时对后一个数做出限制,然后跳过
可以证明修改后面的数一定是最优的,因为还可以兼顾到后面的后面。
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=x*10+c-48;
x=(f ? -x : x);
return;
}
int n;
int a[maxn];
int cal(bool tp){
int lim=a[1];
int ans=0;
for(int i=2;i<=n;i++){
if(tp){
if(i>1&&a[i]<=lim){
++ans;
lim=max(lim,a[i+1])+1;
}
else{
lim=a[i];
}
}
else{
if(i>1&&a[i]>=lim){
++ans;
lim=min(lim,a[i+1])-1;
}
else{
lim=a[i];
}
}
tp=!tp;
}
return ans;
}
int main(){
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
read(n);
for(int i=1;i<=n;i++){
read(a[i]);
}
printf("%d",min(cal(1),cal(0)));
return 0;
}
//^o^
今天时间不多了,先把后三道题放上来
H题本来都看出来了,结果DSU on tree太久没写忘了qwq
F
这道也是DSU on tree

G

H

先看出中序遍历,然后发现其选择不具有连续性,也就是说不一定只选子节点
选的是以它为根的所有子树中最大的两颗符合条件的子树。
对每个点建立一个优先队列,存储以它为根的所有符合条件的子树大小
每次将子节点合并至父亲节点,考虑DSU on tree优化
记录每个点对应的优先队列,每次选择将队列长度小的合并到大的上
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
void read(int& x){
char c;
bool f=0;
while((c=getchar())<48) f|=(c==45);
x=c-48;
while((c=getchar())>47) x=x*10+c-48;
x=(f ? -x : x);
return;
}
priority_queue<int> q[maxn];
int t,n;
int head[maxn],nxt[maxn<<1],e[maxn<<1];
int rt[maxn];
int mp_cnt;
void init_mp(){
memset(head,-1,sizeof(head));
mp_cnt=-1;
}
void add_edge(int u,int v){
e[++mp_cnt]=v;
nxt[mp_cnt]=head[u];
head[u]=mp_cnt;
}
int merge(int u,int v){
if(q[u].size()<q[v].size()) swap(u,v);
while(!q[v].empty()){
q[u].push(q[v].top());
q[v].pop();
}
return u;
}
void dfs(int u,int fa){
for(int i=head[u];~i;i=nxt[i]){
int v=e[i];
if(v==fa) continue;
dfs(v,u);
rt[u]=merge(rt[u],rt[v]);
}
int ans=0;
if(!q[rt[u]].empty()) ans+=q[rt[u]].top(),q[rt[u]].pop();
if(!q[rt[u]].empty()) ans+=q[rt[u]].top(),q[rt[u]].pop();
q[rt[u]].push(ans+1);
}
int main(){
//freopen("tree2.in","r",stdin);
read(t);
while(t--){
read(n);
int u,v;
init_mp();
for(int i=1;i<n;i++){
read(u),read(v);
add_edge(u,v),add_edge(v,u);
}
for(int i=1;i<=n;i++){
rt[i]=i;
while(!q[i].empty()) q[i].pop();
}
dfs(1,1);
printf("%d\n",q[rt[1]].top());
}
return 0;
}
//^o^

浙公网安备 33010602011771号