Codeforces Round #271 (Div. 2)(A,B,C(思维+几何),D(dp),E(线段树维护序列F 线段树+主席树)

题目链接

挑了一场远古场,没想到战绩还不错,直接五题:

A. Keyboard

题意:给你一个键盘,但是Mole会打错,要么都往左边打了,要么都往右边打了,现在第一行输入 L或R代表往左和往右,然后一行字符串,代表打出来的字符,让你求原来的字符

qwertyuiop
asdfghjkl;
zxcvbnm,./

做法:简单模拟一下就可以了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e3+10;
char s[N]="0qwertyuiopasdfghjkl;zxcvbnm,./";
char t[N];
int vis[N],len;
int main()
{
    len=strlen(s);
    for(int i=1;i<len;++i){
        vis[s[i]]=i;
    }
    char ty;
    cin>>ty>>t+1;
    int n=strlen(t+1);
    if(ty=='L'){
        for(int i=1;i<=n;++i){
            int id=vis[t[i]];
            printf("%c",s[id+1]);
        }
    }
    else{
        for(int i=1;i<=n;++i){
            int id=vis[t[i]];
            printf("%c",s[id-1]);
        }

    }
}

B. Worms

题意:给你n长度的序列x,第一堆有 编号1~x[1]  第二堆有编号x[1]+1~x[1]+x[2]  后面以此类推,然后m次询问,x编号在哪堆

做法:求个前缀和,二分一下就行

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e5+10;
int n,a[N],pre[N];
int main()
{
    cin>>n;
    rep(i,1,n)
    {
        scanf("%d",&a[i]);
        pre[i]=pre[i-1]+a[i];
    }
    int m;scanf("%d",&m);
    rep(i,1,m)
    {
        int x;
        scanf("%d",&x);
        int id=lower_bound(pre+1,pre+1+n,x)-pre;
        printf("%d\n",id);
    }
}

C. Captain Marmot

题意:

题意:给你4*n个点,每个点有个原点:x1,y1,和中心点:x0,y0 你可以通过原点逆时针旋转90度几次得到其他三个点,花费是旋转的次数

现在你要求n个组合的4个点 能否 通过旋转(也可以不旋转)得到一个正方形,输出最少的步数,如果不能构成正方形,输出-1

做法:刚开始以为是通过数学公式算出其他三个点,其实不然,画个图,做四个点与原地的x轴和y轴垂线就可以发现规律了。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e3+10;
int n;
struct node
{
    ll x[5],y[5];
}a[N];
struct node1
{
    ll x,y,t;
};
ll dis(ll x1,ll y1,ll x2,ll y2)
{
    return (x1-x2)*(x1-x2)+(y1-y2)*(y1-y2);
}
bool cmp(node1 a,node1 b)
{
    return a.t<b.t;

}
int check(int x1,int y1,int x2,int y2,int x3,int y3,int x4,int y4)
{
    if(x1==x2&&y1==y2) return 0;
    if(x1==x3&&y1==y3) return 0;
    if(x1==x4&&y1==y4) return 0;
    if(x2==x3&&y2==y3) return 0;
    if(x2==x4&&y2==y4) return 0;
    if(x3==x4&&y3==y4) return 0;///有相同的点
    node1 t1[5];
    t1[1]={x2,y2,dis(x1,y1,x2,y2)};
    t1[2]={x3,y3,dis(x1,y1,x3,y3)};
    t1[3]={x4,y4,dis(x1,y1,x4,y4)};//与另外三个点的距离


    node1 t2[5];
    t2[1]={x1,y1,dis(x2,y2,x1,y1)};
    t2[2]={x3,y3,dis(x2,y2,x3,y3)};
    t2[3]={x4,y4,dis(x2,y2,x4,y4)};

    node1 t3[5];
    t3[1]={x1,y1,dis(x1,y1,x3,y3)};
    t3[2]={x2,y2,dis(x3,y3,x2,y2)};
    t3[3]={x4,y4,dis(x3,y3,x4,y4)};

    node1 t4[5];
    t4[1]={x1,y1,dis(x4,y4,x1,y1)};
    t4[2]={x2,y2,dis(x4,y4,x2,y2)};
    t4[3]={x3,y3,dis(x4,y4,x3,y3)};

    sort(t1+1,t1+1+3,cmp);
    sort(t2+1,t2+1+3,cmp);
    sort(t3+1,t3+1+3,cmp);
    sort(t4+1,t4+1+3,cmp);
    int len=t1[1].t;
    if(t1[1].t!=len||t1[2].t!=len) return 0;
    if(t2[1].t!=len||t2[2].t!=len) return 0;
    if(t3[1].t!=len||t3[2].t!=len) return 0;
    if(t4[1].t!=len||t4[2].t!=len) return 0;

    x2=t1[1].x,y2=t1[1].y;
    x3=t1[2].x,y3=t1[2].y;

    if((y2-y1)*(y3-y1)==(x2-x1)*(x1-x3))return 1;
    return 0;

}
int run(node a,node b,node c,node d)
{
    int ans=100;
    rep(i,1,4)
    rep(j,1,4)
    rep(k,1,4)
    rep(l,1,4)
    {
        if(check(a.x[i],a.y[i],b.x[j],b.y[j],c.x[k],c.y[k],d.x[l],d.y[l]))
        {
            ans=min(ans,i+j+k+l-4);
        }

    }

    if(ans==100) ans=-1;
    return ans;
}
int main()
{
    cin>>n;
    rep(i,1,4*n)
    {
        ll x,y,x0,y0;
        cin>>x>>y>>x0>>y0;
        ll dx=x-x0,dy=y-y0;

        a[i].x[1]=x,a[i].y[1]=y;
        a[i].x[3]=x0-dx,a[i].y[3]=y0-dy;

        a[i].x[2]=x0-dy,a[i].y[2]=y0+dx;
        a[i].x[4]=x0+dy,a[i].y[4]=y0-dx;

    }

    for(int i=1;i<=4*n;i+=4){
        int ans=run(a[i],a[i+1],a[i+2],a[i+3]);
        printf("%d\n",ans);
    }


}

D. Flowers

题意:

用RW组成字符串,要求w的个数要k个连续出现,R任意,问字符串长度为[a, b]时,字符串的种类有多少。

做法:简单dp一下即可

首先,我们根据样例可以知道,第i长度的状态数,可以完全继承第i-1长度的状态数,因为对R无限制,只需要在所有的旁边加个R就够了,且不会有重复。

然而,当其长度i可以被k整处的时候,那么就意味着可以继承之前的第i-k长度的状态数,因为W可以再增加k个且连续。

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e5+10;
const ll mod=1e9+7;
ll pre[N],dp[N],n,t,k;
void init()
{
    for(int i=0;i<k;++i) dp[i]=1;
    for(int i=k;i<N;++i) dp[i]=dp[i-1]+dp[i-k],dp[i]%=mod;
    for(int i=1;i<N;++i) {
        pre[i]=(pre[i-1]+dp[i])%mod;
    }
}
int main()
{
    cin>>t>>k;
    init();
    pre[0]=0;
    //for(int i=1;i<=3;++i) printf("i:%d dp:%lld \n",i,pre[i]);
    //printf("%lld\n",pre[3]);
    while(t--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        printf("%lld\n",(pre[r]-pre[l-1]+mod)%mod);
    }
}

E. Pillars

题意:

做法:线段树维护一下到达当前i的最长跳跃次数,用fa数组维护当前i是从哪个地方跳过来的即可。

一眼题,没啥好解释的了

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e5+10;
const ll mod=1e9+7;
int n,fa[N];
ll h[N],d;
ll X[N*4],len;
struct node
{
    int num,id;
}tr[16*N];
int get(ll x)
{
    return lower_bound(X+1,X+1+len,x)-X;
}
node MAX(node a,node b)
{
    if(a.num>b.num) return a;
    return b;
}
node qu(int id,int l,int r,int ql,int qr)
{
    if(ql<=l&&r<=qr) return tr[id];
    node tmp={0,0};
    int mid=l+r>>1;
    if(ql<=mid) tmp=MAX(tmp,qu(id<<1,l,mid,ql,qr));
    if(qr>mid) tmp=MAX(tmp,qu(id<<1|1,mid+1,r,ql,qr));
    return tmp;
}
void up(int id,int l,int r,int pos,int val,int i)
{
    if(l==r){
        if(val>tr[id].num){
            tr[id].num=val;
            tr[id].id=i;
        }
        return ;
    }
    int mid=l+r>>1;
    if(pos<=mid) up(id<<1,l,mid,pos,val,i);
    else up(id<<1|1,mid+1,r,pos,val,i);
    tr[id]=MAX(tr[id<<1],tr[id<<1|1]);
}
int main()
{
    cin>>n>>d;
    rep(i,1,n)
    {
        scanf("%lld",&h[i]);
        X[++len]=h[i];
        X[++len]=h[i]-d;
        X[++len]=h[i]+d;
    }
    sort(X+1,X+1+len);
    len=unique(X+1,X+1+len)-X-1;
    int id=0,ans=0;
    rep(i,1,n)
    {
        int l=get(h[i]-d);
        int r=get(h[i]+d);
        node tmp={0,0};
        tmp=MAX(tmp,qu(1,1,len,1,l));
        tmp=MAX(tmp,qu(1,1,len,r,len));
        fa[i]=tmp.id;
        if(tmp.num+1>ans){
            ans=tmp.num,id=i;
        }
        //printf("i:%d tmp.num:%d\n",i,tmp.num+1);

        up(1,1,len,get(h[i]),tmp.num+1,i);
    }
    stack<int>sta;
    while(id!=0){
        sta.push(id);
        id=fa[id];
    }
    printf("%d\n",sta.size());
    while(sta.size()){
        printf("%d ",sta.top());
        sta.pop();
    }
}

F. Ant colony

题意:问你区间 l,r 之间有多少个数能整除区间内除了这个数的其他的数,然后区间长度减去数的个数就是答案。

做法:求最小值,然后求区间gcd  判断gcd是否等于最小值即可,然后还要求最小值的个数,我这里用主席树维护某个区间内的某个数的个数,这里有点复杂,其实也可以通过最初的build的函数维护当前区间最小值的个数即可

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=1e5+10;
int mx[4*N],X[N],gc[4*N],n,a[N],m,len,mi;
int rt[40*N],ls[40*N],rs[40*N],sum[40*N],cnt;
int get(int x)
{
    return lower_bound(X+1,X+1+len,x)-X;
}
void bu(int id,int l,int r)
{
    if(l==r){gc[id]=a[l];mx[id]=a[l];return ;}
    int mid=l+r>>1;
    bu(id<<1,l,mid);bu(id<<1|1,mid+1,r);
    gc[id]=__gcd(gc[id<<1],gc[id<<1|1]);
    mx[id]=min(mx[id<<1],mx[id<<1|1]);
}
int qu(int id,int l,int r,int ql,int qr)
{
    if(ql<=l&&r<=qr){
        mi=min(mi,mx[id]);
        return gc[id];
    }
    int mid=l+r>>1;
    if(qr<=mid){
        return qu(id<<1,l,mid,ql,qr);
    }
    else if(ql>mid) return qu(id<<1|1,mid+1,r,ql,qr);
    else return __gcd(qu(id<<1,l,mid,ql,mid),qu(id<<1|1,mid+1,r,mid+1,qr));
}
void up1(int pre,int &o,int l,int r,int pos)
{
    o=++cnt;
    ls[o]=ls[pre];
    rs[o]=rs[pre];
    sum[o]=sum[pre];
    if(l==r){
        sum[o]++;
        return ;
    }
    int mid=l+r>>1;
    if(pos<=mid) up1(ls[pre],ls[o],l,mid,pos);
    else up1(rs[pre],rs[o],mid+1,r,pos);
}
int qu1(int pre,int o,int l,int r,int pos)
{
    if(l==r) return sum[o]-sum[pre];
    int mid=l+r>>1;
    if(pos<=mid) return qu1(ls[pre],ls[o],l,mid,pos);
    return qu1(rs[pre],rs[o],mid+1,r,pos);
}
int main()
{
	cin>>n;
	rep(i,1,n){scanf("%d",&a[i]);X[++len]=a[i];}


	bu(1,1,n);
	sort(X+1,X+1+len);
	len=unique(X+1,X+1+len)-X-1;

	rep(i,1,n){
        up1(rt[i-1],rt[i],1,len,get(a[i]));
	}

	cin>>m;
	while(m--)
    {
        int l,r;
        scanf("%d%d",&l,&r);
        mi=1e9+10;
        int gcc=qu(1,1,n,l,r);
        int ans=r-l+1;

        int num=0;
        if(gcc==mi){
            num=qu1(rt[l-1],rt[r],1,len,get(mi));
            ans-=num;
        }
        //printf("gcd:%d mi:%d ans:%d num:%d\n",gcc,mi,ans,num);
        printf("%d\n",ans);
    }
}
发布了498 篇原创文章 · 获赞 66 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/qq_41286356/article/details/104933802