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:

题意是说:

\[(a_i xor b_i)and(a_{i+1} xor b_{i+1})=(a_i xor b_i) \]

如果有解,那么 \(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\) 个空调的温度。

根据题意,一个地方的空调只能被左右两边的空调所影响,有:

\[f[i]=min(f[i],f[i-1]+1,f[i+1]+1) \]

考虑到左右两端都有影响,就需要左右两端都扫描一遍。

#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;
}
posted @ 2021-08-24 19:17  Evitagen  阅读(37)  评论(0编辑  收藏  举报