Codeforces Round #731 (Div. 3) 总结

目录

比赛链接

A. Shortest Path with Obstacle

题意

思路

代码

B.Alphabetical Strings

题意

思路

代码

C. Pair Programming

题意

思路

代码

D. Co-growing Sequence

题意

思路

代码

E. Air Conditioners

题意

思路

代码

F. Array Stabilization (GCD version)

题意

思路

代码

G. How Many Paths?

友情链接

总结


比赛链接

        Dashboard - Codeforces Round #731 (Div. 3) - Codeforces

A. Shortest Path with Obstacle

        Problem - A - Codeforces

题意

        给出三个点A、B、F的二维坐标,问你A和B两点不经过F的最小距离。

思路

        首先先算出AB两点之间的举例,判断F是否在中间,如果在就+2,不在就不动。

        变量一多我就有点晕,几分钟之后才AC

代码

#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<vector>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
ll GCD(ll a,ll b){while(b^=a^=b^=a%=b);return a;}
const int inf=0x3f3f3f3f;
int T,a1,a2,b1,b2,f1,f2,d;
signed main() 
{
    #ifndef ONLINE_JUDGE
		    freopen("IO\\in.txt","r",stdin);
		    freopen("IO\\out.txt","w",stdout);
        #endif
    IOS
    cin>>T;
    while (T--)
    {
        cin>>a1>>a2>>b1>>b2>>f1>>f2;
        d=abs(a1-b1)+abs(a2-b2);
        //cout<<d<<" "<<f2<<" "<<min(a2,b2)<<" "<<max(a2,b2)<<endl;
        if (a1==b1&&f1==a1&&(f2<=max(a2,b2)&&f2>=min(a2,b2))) d+=2;
        if (a2==b2&&f2==a2&&(f1<=max(a1,b1)&&f1>=min(a1,b1))) d+=2;
        cout<<d<<endl;
    }
    return 0;
}

B.Alphabetical Strings

        Problem - B - Codeforces

题意

        给出一个字符串,判断是否合法,合法是从a开始两边一直有递增的

思路

        先确定a的位置,然后去两边双指针去寻找下一个,如果没有那么就是不合法的,最后所有长度都合法,那么就是合法的。

代码

        

#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<vector>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
ll GCD(ll a,ll b){while(b^=a^=b^=a%=b);return a;}
const int inf=0x3f3f3f3f;
string st;
int T,len,pos,l,r;
signed main() 
{
    #ifndef ONLINE_JUDGE
		    freopen("IO\\in.txt","r",stdin);
		    freopen("IO\\out.txt","w",stdout);
        #endif
    IOS
    cin>>T;
    while (T--)
    {
        cin>>st;
        len=st.length();
        pos=-1;
        for (int i=0;i<len;i++)
            if (st[i]=='a') {pos=i;break;}
        //找a的位置
        l=pos,r=pos;
        //双指针
        bool boo=true;
        if (len==1&&st[0]!='a'||pos==-1) boo=false;
        for (int i=2;i<=len;i++)
        {
            if (l>0&&st[l-1]==char(i+'a'-1)) {l--;continue;}
            if (r<len-1&&st[r+1]==char(i+'a'-1)) {r++;continue;}
            //两个指针都没有continue 说明没有找到
            boo=false;
            break;
        }
        if (boo) cout<<"YES\n";
        else cout<<"NO\n";
    }
    return 0;
}

C. Pair Programming

        Problem - C - Codeforces

题意

        两个序列要不打乱各自顺序下合并,满足序列中所有不等于0的数字当前小于等于k,k有一个初始值,如果0的话就k+1

思路

        也是一个贪心双指针,遇到0就加,反正不会有什么影响,k越多越好;如果碰到不是0的,就判断当前k能不能满足,能的话就指向下一个;不可以的话那么序列是无法满足的

代码

#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<vector>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
const int N = 500;
int a[N],b[N],t1,t2,k,n,m,cnt,ans[N],T;
ll GCD(ll a,ll b){while(b^=a^=b^=a%=b);return a;}
const int inf=0x3f3f3f3f;
signed main() 
{
    #ifndef ONLINE_JUDGE
		    freopen("IO\\in.txt","r",stdin);
		    freopen("IO\\out.txt","w",stdout);
        #endif
    IOS
    cin>>T;
    while (T--)
    {
        cin>>k>>n>>m;
        for (int i=1;i<=n;i++) cin>>a[i];
        for (int i=1;i<=m;i++) cin>>b[i];
        t1=1;t2=1;cnt=0;
        bool boo=true;
        while (1)
        {
            if (cnt==n+m) break;
            if (a[t1]==0&&t1<=n)
            {
                ans[++cnt]=a[t1++];
                k++;
                continue;
            }
            if (b[t2]==0&&t2<=m)
            {
                ans[++cnt]=b[t2++];
                k++;
                continue;
            }
            //0的情况
            if (a[t1]<=k&&t1<=n)
            {
                ans[++cnt]=a[t1++];
                continue;
            }
            if (b[t2]<=k&&t2<=m)
            {
                ans[++cnt]=b[t2++];
                continue;
            }
            //不为0的情况
            boo=false;
            break;
            //都没有continue 说明没有办法使得其继续下去
        }
        if (!boo) cout<<-1;
        else for (int i=1;i<=cnt;i++) cout<<ans[i]<<" ";
        cout<<endl;
    }
    return 0;
}

D. Co-growing Sequence

        Problem - D - Codeforces

题意

        给出一个序列,问你当前要加上多少,满足a_{i-1} \&{} a_i==a_{i-1}

思路

        我们可以用先去或得到一个tmp=a[i-1] | a[i];这个就是我们需要达到的数字,然后用去异或来得到a[i]还差多少,输出a[i]^tmp,然后这个tmp赋值给a[i],下一次到i+1的时候用得上

代码

#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<vector>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
ll GCD(ll a,ll b){while(b^=a^=b^=a%=b);return a;}
const int inf=0x3f3f3f3f;
const int N = 2e5+7;
ll t[40],b,a[N],x;
int T,n,tmp;
signed main() 
{
    #ifndef ONLINE_JUDGE
		    freopen("IO\\in.txt","r",stdin);
		    freopen("IO\\out.txt","w",stdout);
        #endif
    IOS
    b=1;
    for (int i=1;i<=31;i++)
    {
        b<<=1;
        t[i]=b-1;
    }
    cin>>T;
    while (T--)
    {
        cin>>n;
        for (int i=1;i<=n;i++) 
            cin>>a[i];
        cout<<0<<" ";
        for (int i=2;i<=n;i++)
        {
            tmp=(a[i]|a[i-1]);
            cout<<(tmp^a[i])<<" ";
            a[i]=tmp;
        }
        
        cout<<endl;
    }
    return 0;
}

E. Air Conditioners

        Problem - E - Codeforces

题意

        k个位置上有空调,温度是t,每隔一个,温度+1,求这个区间内每一处的最小温度

思路

        我做的时候不知道怎么处理一个地方,因为这一个地方有很多东西影响,有左边来的也有右边来的,补题的时候才知道,我们只需要扫两遍,左边右边各一遍即可

        先把每一处全部赋值个inf,再把每个地方的空调温度全部复制给数组上。左边扫一遍是处理所有空调向右的影响,这样就不用管我之前所说的,右边扫回来也是同理。看代码吧

代码

#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<vector>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
ll GCD(ll a,ll b){while(b^=a^=b^=a%=b);return a;}
const int inf=0x3f3f3f3f;
const int N = 3e5+7;
ll a[N],n,k,T,pos[N];
signed main() 
{
    #ifndef ONLINE_JUDGE
		    freopen("IO\\in.txt","r",stdin);
		    freopen("IO\\out.txt","w",stdout);
        #endif
    IOS
    cin>>T;
    while (T--)
    {
        cin>>n>>k;
        memset(a,0x3f/2,sizeof(a));
        for (int i=1;i<=k;i++) cin>>pos[i];
        for (int i=1;i<=k;i++) cin>>a[ pos[i] ];
        for (int i=2;i<=n;i++) a[i]=min(a[i],a[i-1]+1);
        for (int i=n-1;i>=1;i--) a[i]=min(a[i],a[i+1]+1);
        for (int i=1;i<=n;i++) cout<<a[i]<<" ";
        cout<<endl;
    }
    return 0;
}

F. Array Stabilization (GCD version)

        Problem - F - Codeforces

题意

        给出一个序列,每一次操作使得a[i]和a[i+1]取gcd然后给a[i],当越界的时候也就是i=n的时候,a[n]与a[1]取gcd,问至少多少次之后,整个序列相等

思路

        我们先来想一想暴力算法,然后再优化。

        先枚举次数,从1-n,然后枚举每个区间开始,然后查询的gcd,该时间复杂度是O(n^3)

        优化枚举区间长度的GCD:ST表

        优化枚举区间长度(次数):二分答案

         ST表以前都是用来去min或者max的,但是只需要将其改成gcd即可,学到了。二分答案是因为其有单调性,“不合法”、“不合法”、...、“不合法”、“合法”、...、“合法”

        但是我代码...不知道错哪了,求大神解答

代码

        

#include<stack>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<queue>
#include<cstring>
#include<deque>
#include<vector>
#include<iostream>
#include<map>
#include<set>
#include<iomanip>
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
#define ll long long
using namespace std;
ll GCD(ll a,ll b){while(b^=a^=b^=a%=b);return a;}
const int inf=0x3f3f3f3f;
const int N = 4e5+7;
int lg2[N],f[N][30],n,T,l,r,mid;
inline int query(int l,int r)
{
    int w=lg2[r-l+1];
    //cout<<"!"<<l<<" "<<r<<" "<<f[l][w]<<" "<<f[r-(1<<w)+1][w]<<endl;
    return GCD(f[l][w],f[r-(1<<w)+1][w]);
}
inline void ST()
{
	for (int i=n;i>=1;i--)
		for (int j=1;i+(1<<j)-1<=n;j++)
			f[i][j]=GCD(f[i][j-1],f[i+(1<<j-1)][j-1]);
}
inline void init()
{
	for (int i=2;i<=n;i++)
		lg2[i]=lg2[i>>1]+1;
}
inline bool check(int k)
{
    int tmp=-1;
    if (k==0) return true;
    for (int i=1;i<=n;i++)
    {
        int t=query(i,i+k-1);
        //cout<<t<<endl;
        if (tmp==-1) tmp=t;
        else if (tmp!=t) return false;
    }
    return true;
}
signed main() 
{
    #ifndef ONLINE_JUDGE
		    freopen("IO\\in.txt","r",stdin);
		    freopen("IO\\out.txt","w",stdout);
        #endif
    IOS
    cin>>T;
    init();
    while (T--)
    {
        cin>>n;
        for (int i=1;i<=n;i++) cin>>f[i][0];
        for (int i=n+1;i<=2*n;i++) f[i][0]=f[i-n][0];
        n<<=1;
        ST();
        n>>=1;
        //cout<<"T="<<T<<endl;
        int l=0,r=n,mid;
            while(l<r){
                //out<<l<<" "<<r<<endl;
                mid=(l+r)/2;
                if(check(mid)){
                    r=mid;
                }
                else{
                    l=mid+1;
                }
            }
            if(r)r--;
            cout<<r<<endl;
    }
    return 0;
}
/*
INPUT
1
5
5 13 2 10 11
OUTPUT
4
ANSWER
2
*/


G. How Many Paths?

        Problem - G - Codeforces

        待补

友情链接

        Codeforces Round #731 (Div. 3) +382_TheSunspot的博客-CSDN博客

总结

        ST(Sparse Table)表,中文名稀疏表,是一种数据结构。

        ST表常用于解决可重复贡献问题

        什么是可重复贡献问题?

        举例来说:要你求10个数中的最大数,你完全可以先求前6个数的GCD。虽然中间有几个数被重复计算了,但并不影响最后的答案。

        常见的可重复贡献问题有:区间最值、区间按位和、区间按位或、区间GCD等。而像区间和这样的问题就不是可重复贡献问题。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值