CF1547
CF1547
A:
三点在同一条线上,且障碍点在中间,就需要 \(+2\)
直接曼哈顿距离即可。
#include<bits/stdc++.h>
using namespace std;
int ax,ay,bx,by,fx,fy;
bool flag;
int main(){
int t;
cin>>t;
while(t--){
cin>>ax>>ay;
cin>>bx>>by;
cin>>fx>>fy;
int smal=abs(ax-bx)+abs(ay-by);
flag=0;
if(ax==fx&&bx==fx&&((ay<fy&&by>fy)||(ay>fy&&by<fy)))flag=1;
if(ay==fy&&by==fy&&((ax<fx&&bx>fx)||(ax>fx&&bx<fx)))flag=1;
if(flag==1) smal+=2;
cout<<smal<<endl;
}
return 0;
}
B:
两边进行递推,当前可以取到的字符必须是:
当前字符串长度 \(len+'a'-1\) ,左边取到了就 \(L++,len--\),右边就 \(R++,len--\)
注意结束情况是 \(L>R\) 即可。
#include<bits/stdc++.h>
using namespace std;
int T,cnt[30];
char s[30];
int main(){
cin>>T;
while(T--){
scanf("%s",s+1); int len=strlen(s+1),L=1,R=len; bool flag=0;
while(L<=R){
if(s[L]=='a'-1+len) L++,len--;
else if(s[R]=='a'-1+len) R--,len--;
else{ flag=1; break;}
}
if(flag==0) puts("YES");
else puts("NO");
}
// system("pause");
return 0;
}
C:
简单的模拟题。
我们贪心看 \(a\) 序列是否能进行操作,如果不行再进行 \(b\) 序列的操作。
模拟一下过程即可,用队列比较清晰。
#include<bits/stdc++.h>
using namespace std;
const int N=1e2+5;
int T,k,n,m; queue<int> a,b,c;
int main(){
cin>>T;
while(T--){ bool flag=0;
scanf("%d%d%d",&k,&n,&m);
for(int i=1,x;i<=n;i++) scanf("%d",&x),a.push(x);
for(int i=1,x;i<=m;i++) scanf("%d",&x),b.push(x);
while(!a.empty()||!b.empty()){
if((a.front()>k&&b.front()>k)||(b.empty()&&a.front()>k)||(a.empty()&&b.front()>k)) {flag=1; break;}
int x=a.front();
while(x<=k&&!a.empty()){if(x==0) k++; c.push(x); a.pop(); x=a.front();}
x=b.front();
while(x<=k&&!b.empty()){if(x==0) k++; c.push(x); b.pop(); x=b.front();}
}
if(flag==1) printf("-1");
else while(!c.empty()){printf("%d ",c.front()); c.pop();} puts("");
while(!c.empty())c.pop();
while(!a.empty())a.pop();
while(!b.empty())b.pop();
}
// system("pause");
return 0;
}
D:
题意是说:
如果有解,那么 \(b_1=0\) 一定是字典序最小。那么我们只需要模拟这个过程即可。
也就是 \(b_2=(a_2 and a_1)^a_2\)
直接输出即可。
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,T,x,y;
int main(){
cin>>T;
while(T--){
scanf("%d%d",&n,&x); printf("0");
while(--n){
scanf("%d",&y); printf(" %d",((y|x)^y)); x|=y;
}
cout<<endl;
}
// system("pause");
return 0;
}
E:
我们设 \(f_i\) 为第 \(i\) 个空调的温度。
根据题意,一个地方的空调只能被左右两边的空调所影响,有:
考虑到左右两端都有影响,就需要左右两端都扫描一遍。
#include<bits/stdc++.h>
using namespace std;
const int M=3e5+5;
int a[M],b[M],c[M],T,n,m;
bool vis[M];
int main(){
cin>>T;
while(T--){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)c[i]=0x3f3f3f3f;//初始化最大值
for(int i=1;i<=m;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++) scanf("%d",&b[i]);
for(int i=1;i<=m;i++)c[a[i]]=b[i];//有空调的地方温度先暂时是空调的温度来转移
for(int i=2;i<=n;i++)c[i]=min(c[i],c[i-1]+1);//从前往后扫
for(int i=n-1;i>=1;i--)c[i]=min(c[i],c[i+1]+1);//从后往前扫
for(int i=1;i<=n;i++)printf("%d ",c[i]);puts("");
}
// system("pause");
return 0;
}
F:
我们思考一下:
两个数取 \(gcd\) , 相当于保留两个数的公共质因子
对于整个序列执行无数次 \(gcd\) 操作后, 等价于序列中每个数字变为原序列中所有公共质因子的乘积
因此我们不妨执行 \(a[] /= gcd(a[])\). 此时我们最终得到的序列一定是全1序列.
因此我们就有目标:执行完多少次操作后, 使得序列中每一个数字都等于1.
互质的情况不用考虑,我们考虑不互质的情况,假设存在公因子2。
我们观察可以发现, 如果\(a[i], a[i + 1], …, a[i + k]\)都存在公因子 \(2\),$ a[k + 1]$不存在因子2, 则我们需要k轮操作, 才能把 \(a[i]\)变为1.
得出结论: 对于每一个位置\(i\), 我们开始连续取\(gcd\), 当第一次出现 \(gcd(a[i], a[i + 1], …, a[i + k]) == 1\) 时, 表示\(i\)位置需要操作\(k\)轮才能变为1.
那么对于本题, 我们把所有位置的\(k\)取\(max\)即为最终答案.
线段树维护每个区间 \(gcd\) 的信息. 对于每个位置查询最靠左 \(gcd == 1\) 的位置即可
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=4e5+5;
struct node{
int l,r,val;
}t[N<<2];
int T,n,a[N];
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
void pushup(int x){
t[x].val=gcd(t[x<<1].val,t[x<<1|1].val);
}
void build(int l,int r,int x){
t[x]={l,r,a[l]};
if(l==r) return ;
int mid=l+r>>1;
build(l,mid,x<<1); build(mid+1,r,x<<1|1);
pushup(x);
}
int ask(int l,int r,int x){
if(l<=t[x].l&&r>=t[x].r) return t[x].val;
int mid=t[x].l+t[x].r>>1,res=0;
if(l<=mid) res=ask(l,r,x<<1);
if(r>mid) res=gcd(res,ask(l,r,x<<1|1));
return res;
}
int main(){
cin>>T;
while(T--){
scanf("%d",&n); int d=0,ans=0;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),d=gcd(a[i],d);
// cout<<d<<endl;
if(d!=1) for(int i=1;i<=n;i++) a[i]/=d;
for(int i=1;i<=n;i++) a[n+i]=a[i]; n*=2;
build(1,n,1);
for(int i=1;i<=n/2;i++){
if(a[i]==1) continue;
int l=i+1,r=n;
while(l<r){
int mid=l+r>>1,cou=ask(i,mid,1);
if(cou==1) r=mid;
else l=mid+1;
}
ans=max(ans,r-i);
}
printf("%d\n",ans);
}
// system("pause");
return 0;
}