13th Programming Competition and ACM Selection Competition of Beijing University of Information Technology

13th Programming Competition and ACM Selection Competition of Beijing University of Information Technology


A.lzh's trampoline


lzh's trampoline


From greed, you know that the starting point of each trip must be the first number not to be 1, but what if the time complexity is very high for the first simulated jump?

We can calculate the contribution of each trampoline to the answer, then add it up. If sum[i] is the number of times to jump to the position I on the left, then the contribution to the position I can be calculated in different cases:

If a [ i ] > 1 a[i]>1 When a [i]>1, it only has a + 1 Effect on the [i+2,i+a[i]] interval.

If s u m [ i ] ≥ a [ i ] sum[i]\ge a[i] When sum[i] (> a[i]), the I position has changed to 1, so this position has no contribution to the answer, but it has an effect on the [i+1,i+a[i]] interval, on the [i+2,i+a[i]] interval, +1 on the i+1 position.

If s u n m [ i ] < a [ i ] sunm[i]<a[i] When sunm[i]<a[i], part of it comes from the left, which cannot be added to the contribution of the answer, only the remaining a[i]-sum[i]-1 is the contribution of location I to the answer.

That would be equivalent to an interval modification operation and a single query operation at the end, so what can be solved? Segment trees, tree arrays, differences can be solved. (Segment Tree Survey Meeting T)


Reference code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=5e3+10;
ll a[maxn],sum[maxn],n;
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%lld",&n);
        memset(sum,0,sizeof(sum));
        for(int i=1;i<=n;i++)
        scanf("%lld",&a[i]);
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            sum[i]+=sum[i-1];
            if(sum[i]>=a[i])
            {
                if(i+1<=n)
                {
                    sum[i+1]+=sum[i]-a[i];
                    sum[i+2]-=sum[i]-a[i];
                    sum[i+1]++;
                    sum[min(n,i+a[i])+1]--;
                }
            }
            else
            {
                if(sum[i]==0)
                {
                    ans+=a[i]-1;
                    if(i+2<=n)
                    {
                        sum[i+2]++;
                        sum[min(n,i+a[i])+1]--;
                    }
                }
                else
                {
                    ll l=i+a[i]-sum[i]+1,r=i+a[i];
                    if(l<=n)
                    {
                        sum[l]++;
                        sum[min(n,r)+1]--;
                    }
                    ans+=a[i]-sum[i]-1;
                    if(i+2<=n)
                    {
                        sum[i+2]++;
                        sum[min(n,l-1)+1]--;
                    }
                }
            }
        }
        printf("%lld\n",ans);
    }
    system("pause");
    return 0;
}

B. so-called river crossing


So-called river crossing


It always feels like my time complexity will explode, but when I learn to submit it it, it's only 7ms. That's great!!!

I think it's about maintaining two intersecting circles with a set and then determining if the circle intersecting y=0 is in a set plus y=H.


Reference code:

#include<bits/stdc++.h>
using namespace std;
const double PI = acos(-1.0);
const double eps = 1e-8;
const int maxn=1e4+10;
int s[maxn],n;
double h;
int sgn(double x)
{
	if (fabs(x) < eps)return 0;
	else return x < 0 ? -1 : 1;
}
int cmp(double x, double y)
{
	if (fabs(x - y) < eps||x < y) return 0;
	return 1;
}
struct Point {
	double x, y;
	Point() {}
	Point(double x, double y) :x(x), y(y) {}
	Point operator + (Point B) { return Point(x + B.x, y + B.y); }
	Point operator - (Point B) { return Point(x - B.x, y - B.y); }
	Point operator * (double k) { return Point(x * k, y * k); }
	Point operator / (double k) { return Point(x / k, y / k); }
};
struct Circle {
	Point c;
	double r;
	Circle() {}
	Circle(Point c, double r) :c(c), r(r) {}
	Circle(double x, double y, double _r) { c = Point(x, y), r = _r; }
}a[maxn];
double dis(Point A, Point B)
{
	return sqrt((A.x - B.x) * (A.x - B.x) + (A.y - B.y) * (A.y - B.y));
}
void init()
{
    for(int i=1;i<=n;i++)
    s[i]=i;
}
int find(int x)
{
    if(x!=s[x])s[x]=find(s[x]);
    return s[x];
}
void lh(int x,int y)
{
    x=find(x),y=find(y);
    if(x!=y)s[x]=s[y];
}
int main()
{
    scanf("%d%lf",&n,&h);
    init();
    for(int i=1;i<=n;i++)
    {
        double x,y,r;
        scanf("%lf%lf%lf",&x,&y,&r);
        a[i]={x,y,r};
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=i+1;j<=n;j++)
        {
            double d=dis(a[i].c,a[j].c);
            if(cmp(d,a[i].r+a[j].r)==0)lh(i,j);
        }
    }
    vector<int>v1,v2;
    for(int i=1;i<=n;i++)
    {
        if(sgn(a[i].c.y-a[i].r)<=0)v1.push_back(i);
        if(a[i].c.y+a[i].r>=h)v2.push_back(i);
    }
    int flag=0;
    for(int i=0;i<v1.size();i++)
    {
        for(int j=0;j<v2.size();j++)
        {
            int x,y;
            x=find(v1[i]);
            y=find(v2[j]);
            if(x==y)
            {
                flag=1;
                break;
            }
        }
        if(flag==1)break;
    }
    if(flag==0)printf("No\n");
    else printf("Yes\n");
    system("pause");
    return 0;
}


C. Traveller Question 1


Traveller Question 1


If you don't have a way of thinking, you can decide where to start and then minimize the situation.


Reference code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
int main()
{
    int n,x;
    scanf("%d%d",&n,&x);
    ll minn=LLONG_MAX,maxx=LLONG_MIN;
    for(int i=1;i<=n;i++)
    {
        ll xx;
        scanf("%lld",&xx);
        minn=min(minn,xx);
        maxx=max(maxx,xx);
    }
    if(x<=minn)printf("%lld\n",maxx-x);
    else if(x>=maxx)printf("%lld\n",x-minn);
    else printf("%lld\n",min(2*(x-minn)+maxx-x,2*(maxx-x)+x-minn));
    system("pause");
    return 0;
}

D. Traveler problem 2


Traveller Question 2


Greedy thinking knows that for each mountain, it can only arrive and leave once, so n mountains can form a ring. And when you reach the highest mountain, the return process must be done by ladders. When you reach the highest mountain, the process may be ladder or airplane.

For ease of calculation, we can assume that all ladders are used, so the sum is ∑ x i \sum x_i Sigma xi, for some h [ j ] > h [ i ] + x [ i ] h[j]>h[i]+x[i] Mountains of h[j]>h[i]+x[i] can only be mounted by airplane, so another contribution to the answer is h [ j ] − h [ i ] − x [ i ] h[j]-h[i]-x[i] h[j]h[i]x[i], so the answer is ∑ x i \sum x_i ∑xi​+ ∑ h [ j ] − h [ i ] − x [ i ] \sum h[j]-h[i]-x[i] _h[j]h[i]x[i], because the front is fixed, the smallest answer needs to be followed by the smallest one. You only need to maintain one after the calculation h [ i ] + x [ i ] h[i]+x[i] The maximum value of h[i]+x[i] is sufficient.


Reference code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
int n;
struct node{
    ll h,x,maxh;
}a[maxn];
bool cmp(node xx,node yy)
{
    return xx.h<yy.h;
}
int main()
{
    scanf("%d",&n);
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld%lld",&a[i].h,&a[i].x);
        ans+=a[i].x;
        a[i].maxh=a[i].h+a[i].x;
    }
    sort(a+1,a+1+n,cmp);
    ll maxx=a[1].maxh;
    for(int i=2;i<=n;i++)
    {
        if(a[i].h>maxx)ans+=(a[i].h-maxx);
        maxx=max(maxx,a[i].maxh);
    }
    printf("%lld\n",ans);
    system("pause");
    return 0;
}


E. Xiaofei and Fib Sequences


Xiaofei and Fib Number Columns


about ( x i × x j + 1 ) (x_i\times x_j +1)%2 (xi *xj +1) As you can see from this formula, if you want to contribute 1 to the answer, you can x i , x j x_i,x_j xi, xj are all even numbers and there is an even number in an odd number.

That's not easy. Find the Fiborachi number of the first n terms, and count the odd and even numbers. The answer is e v e n × ( e v e n − 1 ) ÷ 2 + o d d × e v e n even\times (even-1)\div 2+odd\times even even×(even−1)÷2+odd×even


Reference code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=5e4+10;
ll a[maxn],sum1,sum2;
int n;
void init()
{
    a[1]=1,a[2]=1;
    sum1=2;
    for(int i=3;i<=n;i++)
    {
        a[i]=a[i-1]+a[i-2];
        a[i]%=2;
        if(a[i]==1)sum1++;
        else sum2++;
    }
}
int main()
{
    scanf("%d",&n);
    if(n==1)printf("0\n");
    else 
    {
        init();
        //cout<<sum1<<" "<<sum2<<endl;
        ll x,y;
        if(sum2<2)y=0;
        else y=(sum2-1)*sum2/2;
        x=sum1*sum2;
        printf("%lld\n",x+y);
    }
    system("pause");
    return 0;
}


F. Fun music games


Fun music games


If you don't have any idea, just simulate it.


Reference code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e3+10;
char a[maxn][10],op[10];
vector<int>v[maxn];
int n,m;
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++)
    {
        for(int j=1;j<=7;j++)
        a[i][j]=' ';
    }
    for(int i=1;i<=n;i++)
    {
        int x,y;
        scanf("%s%d%d",op,&x,&y);
        if(strcmp(op,"tap")==0)a[x][y]='O';
        else a[x][y]='X';
        v[x].push_back(y);
    }
    for(int i=1;i<=m;i++)
    {
        if(v[i].size()<=1)continue;
        sort(v[i].begin(),v[i].end());
        for(int j=v[i][0];j<=v[i][v[i].size()-1];j++)
        {
            if(a[i][j]==' ')a[i][j]='-';
        }
    }
    for(int i=m;i>=1;i--)
    {
        printf("|");
        for(int j=1;j<=7;j++)
        printf("%c",a[i][j]);
        printf("|\n");
    }
    printf("+-------+\n");
    system("pause");
    return 0;
}

G.ranko's Watch


ranko's Watch


Just get all the values for two times directly, and get the minimum and maximum values as far as possible. Simulations are pure and technical.


Reference code:

#include<bits/stdc++.h>
using namespace std;
char a[10],b[10];
vector<int>v1,v2;
void dfs_a(int st,int num,int sum)
{
    if(st==5)
    {
        v1.push_back(sum+num);
        return ;
    }
    if(a[st]==':')
    {
        sum=num*60;
        dfs_a(st+1,0,sum);
    }
    else if(a[st]!='?')dfs_a(st+1,num*10+(a[st]-'0'),sum);
    else
    {
        if(st==0)
        {
            for(int i=0;i<=2;i++)dfs_a(st+1,i,sum);
        }
        else if(st==1)
        {
            for(int i=0;i<=9;i++)
            dfs_a(st+1,min(23,num*10+i),sum);
        }
        else if(st==3)
        {
            for(int i=0;i<=5;i++)
            dfs_a(st+1,i,sum);
        }
        else if(st==4)
        {
            for(int i=0;i<=9;i++)
            dfs_a(st+1,min(59,num*10+i),sum);
        }
    }
}
void dfs_b(int st,int num,int sum)
{
    if(st==5)
    {
        v2.push_back(sum+num);
        return ;
    }
    if(b[st]==':')
    {
        sum=num*60;
        dfs_b(st+1,0,sum);
    }
    else if(b[st]!='?')dfs_b(st+1,num*10+(b[st]-'0'),sum);
    else
    {
        if(st==0)
        {
            for(int i=0;i<=2;i++)dfs_b(st+1,i,sum);
        }
        else if(st==1)
        {
            for(int i=0;i<=9;i++)
            dfs_b(st+1,min(23,num*10+i),sum);
        }
        else if(st==3)
        {
            for(int i=0;i<=5;i++)
            dfs_b(st+1,i,sum);
        }
        else if(st==4)
        {
            for(int i=0;i<=9;i++)
            dfs_b(st+1,min(59,num*10+i),sum);
        }
    }
}
int main()
{
    scanf("%s%s",a,b);
    dfs_a(0,0,0);
    dfs_b(0,0,0);
    sort(v1.begin(),v1.end());
    sort(v2.begin(),v2.end());
    int maxx=INT_MIN,minn=INT_MAX;
    for(int i=0;i<v1.size();i++)
    {
        for(int j=0;j<v2.size();j++)
        {
            if(v1[i]<v2[j])
            {
                maxx=max(v2[j]-v1[i],maxx);
                minn=min(minn,v2[j]-v1[i]);
            }
        }
    }
    printf("%d %d\n",minn,maxx);
    system("pause");
    return 0;                                                                                                                                                                
}

H. Letter Collection


Letter Collection


Simple dp problem, and the equation of state is easy to derive d p [ i ] [ j ] = m a x ( d p [ i − 1 ] [ j ] , d p [ i ] [ j − 1 ] ) + a [ i ] [ j ] dp[i][j]=max(dp[i-1][j],dp[i][j-1])+a[i][j] dp[i][j]=max(dp[i_1][j],dp[i][j_1])+a[i][j], just work with the values of the letters l, o, v, e.

Reference code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=510;
int a[maxn][maxn],n,m;
int dp[maxn][maxn];
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            char x;
            scanf(" %c",&x);
            if(x=='l')a[i][j]=4;
            else if(x=='o')a[i][j]=3;
            else if(x=='v')a[i][j]=2;
            else if(x=='e')a[i][j]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
            dp[i][j]=max(dp[i-1][j],dp[i][j-1])+a[i][j];
    }
    printf("%d\n",dp[n][m]);
    system("pause");
    return 0;
}

I. Digital Staining


Digital Staining


Not studied yet, the old vegetable chicken is ready.



J. Xiao Hong's Wish


Xiao Hong's Wish


Reference code:

10


K. Small Red Tree


Little Red Tree


Directly using sz[i] to indicate the size of the subtree with I as the root node, s z [ i ] = ∑ s z [ j ] sz[i]=\sum sz[j] sz[i]=sz[j] (j is the son of i), preprocess all SZ first, O(1) will solve when asked.


Reference code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
char a[maxn];
int h[maxn],n,cnt,sz[maxn];
struct Edge{
    int to;
    int next;
}edge[maxn];
void add(int u,int v)
{
    edge[++cnt].to=v;
    edge[cnt].next=h[u];
    h[u]=cnt;
}
void dfs(int u)
{
    if(a[u]=='R')sz[u]=1;
    for(int i=h[u];~i;i=edge[i].next)
    {
        int j=edge[i].to;
        dfs(j);
        sz[u]+=sz[j];
    }
}
int main()
{
    scanf("%d",&n);
    memset(h,-1,sizeof(h));
    for(int i=2;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        add(x,i);
    }
    scanf("%s",a+1);
    dfs(1);
    int q;
    scanf("%d",&q);
    while(q--)
    {
        int u;
        scanf("%d",&u);
        printf("%d\n",sz[u]);
    }
    system("pause");
    return 0;
}

L. Rearrange Strings


Rearrange strings


Simple Constructive Question. First decide when to output No. Output of no should occur more often than ( n + 1 ) / 2 (n+1)/2 (n+1)/2, the rest is yes.

What about yes? Because adjacent characters are different, you can start with the character that appears most often in a good position and then place it in the position of + 2 each time. Because each position can be changed by 1 + 2 x or person 2 + 2 x 1+2x or 2+2x 1+2x or 2+2x means, so after 1+2x, you can place all the remaining characters at 2+2x, which ensures that adjacent characters are different.


Reference code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
#define PI pair<int,char>
int vis[maxn];
PI p[30];
int n;
bool cmp(PI x,PI y)
{
    return x.first>y.first;
}
int main()
{
    scanf("%d",&n);
    for(int i=0;i<26;i++)
    p[i]={0,'a'+i};
    for(int i=1;i<=n;i++)
    {
        char op;
        scanf(" %c",&op);
        p[op-'a'].first++;
    }
    sort(p,p+26,cmp);
    if(p[0].first>(n+1)/2)printf("no\n");
    else
    {
        int idx=1;
        memset(vis,-1,sizeof(vis));
        for(int i=0;i<26;i++)
        {
            if(p[i].first==0)break;
            while(p[i].first!=0)
            {
                if(vis[idx]==-1)
                {
                    vis[idx]=p[i].second-'a';
                    p[i].first--;
                }
                idx+=2;
                if(idx>n)idx=2;
            }
        }
        printf("yes\n");
        for(int i=1;i<=n;i++)
        {
            char x='a'+vis[i];
            printf("%c",x);
        }
        printf("\n");
    }
    system("pause");
    return 0;
}

If there is a problem, welcome big guys to believe it privately!!!!!!!

Tags: C Algorithm

Posted on Sun, 12 Sep 2021 12:28:40 -0400 by mfallon