【Codeforces 1462】Codeforces Round #690 (Div. 3) | Complete solution

Happy Ake, Ake has DIV3

Contest connection: https://codeforces.com/contest/1462

This game is pretty simple.

table of Contents

A. Favorite Sequence

Main idea:

Question idea:

Code:

B. Last Year's Substring

Main idea:

Question idea:

Code:

C. Unique Number

Main idea:

Question idea:

Code:

D. Add to Neighbour and Remove

Main idea:

Question idea:

Code:

E2. Close Tuples (hard version)

Main idea:

Question idea:

Code:

F. The Treasure of The Segments

Main idea:

Question idea:

Code:


 

A. Favorite Sequence

Main idea:

Given a sequence, output the sequence left and right in the order of the questions

Question idea:

Water question, simulate according to the meaning of the question

Code:

ll n,m,p;
ll a[maxn];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);
        for(int i=1;i<=n;i++) read(a[i]);
        int l = 1,r = n;
        while(l<r){
            printf("%lld %lld ",a[l],a[r]);
            l++;
            r--;
        }
        if(l == r) printf("%lld\n",a[l]);
        else printf("\n");
    }
    return 0;
}

B. Last Year's Substring

Main idea:

Give a string of numbers and ask if you can delete the substring at most once to make the final string "2020"

Question idea:

Consider at most one operation, so you can only delete the substring in the middle, so just judge the boundary.

Code:

ll n,m,p;
char s[maxn];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);
 
        scanf("%s",s+1);
        if(n<4) printf("NO\n");
        else{
            if(s[1] == '2' && s[2] == '0' && s[3] == '2' && s[4] == '0') printf("YES\n");
            else if(s[1] == '2' && s[2] == '0' && s[3] == '2' && s[n] == '0') printf("YES\n");
            else if(s[1] == '2' && s[2] == '0' && s[n-1] == '2' && s[n] == '0') printf("YES\n");
            else if(s[1] == '2' && s[n-2] == '0' && s[n-1] == '2' && s[n] == '0') printf("YES\n");
            else if(s[n-3] == '2' && s[n-2] == '0' && s[n-1] == '2' && s[n] == '0') printf("YES\n");
            else printf("NO\n");
        }
    }
    return 0;
}

C. Unique Number

Main idea:

Ask if the sum of digits is equal to x, and the digits are different from each other, the smallest number

Question idea:

Considering that the numbers are different from each other, so a total of 2 to the 10th power is possible

Just enumerate in binary

Code:

int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);
        int ans = 1e9+7;
        for(int i=0;i<(1<<10);i++){
            int res = 0,temp = 0;
            for(int k=0;k<10;k++){
                if(i>>k&1){
                    res += k;
                    a[++temp] = k;
                }
            }
            if(res == n){
                if(a[1] == 0) swap(a[1],a[2]);
                int tempx = 0;
                for(int k=1;k<=temp;k++) tempx = tempx*10+a[k];
                ans = min(ans,tempx);
            }
        }
        printf("%d\n",ans == mod?-1:ans);
    }
    return 0;
}

D. Add to Neighbour and Remove

Main idea:

Abstract: Given a sequence, ask how many segments you can divide into, so that the sum of each segment is equal.

The final answer is: n-number of segments

Question idea:

There is a simple way of thinking, directly considering the sum of the final state, then this sum must be a factor of the sum

Just check each and every one

Now consider what if the sum is large?

Here is a way to write interval dp, which has nothing to do with s.. The idea is quite simple. Consider that dp[i][k] represents the equal value of the first i divided into k segments.

Then get a n^3 violence, use map to optimize it

This makes me very dumb..

Code:

ll n,m,p;
ll num[maxn],sum[maxn];
int dp[3005][3005];
int pre[3005];
unordered_map<ll,int>mp[3005];
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);
 
        for(int i=1;i<=n;i++) {
            read(num[i]);
            sum[i] = sum[i-1]+num[i];
            mp[i].clear();
        }
        int mx = 1;
        for(int i=1;i<=n;i++)
            for(int k=1;k<=n;k++)
                dp[i][k] = -1;
 
       for(int i=1;i<=n;i++){
            dp[i][1] = sum[i];
            for(int k=2;k<=i;k++){
                int op = mp[k-1][sum[i]];
                if(op) dp[i][k] = sum[i]-sum[op];
            }
            for(int k=1;k<=i;k++)
                if(~dp[i][k]) mp[k][dp[i][k]+sum[i]] = i;
       }
        for(int i=n,k=0;i>=1;i--,k++){
            if(dp[n][i]!=-1){
                printf("%d\n",k);
                break;
            }
        }
    }
    return 0;
}

E2. Close Tuples (hard version)

Main idea:

Given a sequence of length n, ask how many subsequences of length m satisfy the sequence maximum value-sequence minimum value <=k

Question idea:

Enumerate the minimum value of the final answer, and then judge the number of combinations

Assuming that the minimum value of the current enumeration is x, then you need to know how many [x, x+k] there are: this operation can also be done by taking double pointers. In order to simply write a tree array, the result can be divided into two if you think of it. ..

Then respectively enumerate the number of minimum values

Code:

ll n,m,p;
ll num[maxn];
ll sum[maxn];
int vis[maxn];
ll fac[maxn];
ll qpow(ll a,ll b){
    ll ans=1;
    while(b){
        if(b&1)ans=ans*a%mod;
        a=a*a%mod;
        b>>=1;
    }return ans;
}
ll cal(int m,int n){
    if(m<n) return 0;
    return ((fac[m]*qpow(fac[m-n],mod-2))%mod*(qpow(fac[n],mod-2))%mod)%mod;
}
void add(int pos){
    while(pos <= n){
        sum[pos] ++;
        pos += pos&-pos;
    }
}
ll GetSum(int pos){
    ll ans = 0;
    while(pos){
        ans += sum[pos];
        pos -= pos&-pos;
    }return ans;
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);read(m);read(p);
        for(int i=1;i<=n;i++) read(num[i]);
        for(int i=1;i<=n;i++) sum[i] = 0,vis[i] = 0;
        for(int i=1;i<=n;i++) vis[num[i]]++;
        fac[0] = 1;
        for(int i=1;i<=n;i++) fac[i] = (fac[i-1]*i)%mod;
        for(int i=1;i<=n;i++) add(num[i]);
        ll ans = 0;
        for(int i=1;i<=n;i++){
            if(vis[i]){
                ll temp = GetSum(min(i+p,n)) - GetSum(i-1);
                for(int k=1;k<=min(m,vis[i]*1ll);k++){
                    ans = (ans + (cal(vis[i],k)*cal(temp-vis[i],m-k))%mod)%mod;
                }
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}

F. The Treasure of The Segments

Main idea:

Define a line segment set to be good, if and only if there is a line segment that intersects all other line segments, at least delete a few line segments to make this line segment set good

Question idea:

The obvious idea is to enumerate which line segment makes this line segment set good

So what line segments are required to intersect the line segment, use [total number-the number of line segments intersecting with this line segment], which is the number of disjoint line segments

Finally, for the answer of each line segment, just take one min

There are many ways to do this question, because the coordinates are too large, and the chair tree is used to dynamically open the point (too lazy to discretize)

Code:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define d(x) printf("%lld\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e17;
const ll maxn = 2e5+700;
const int mod= 1e9+7;
const int up = 1e9;
template<typename T>inline void read(T &a){char c=getchar();T x=0,f=1;while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
struct node{
    int a,b;
    bool friend operator<(node a,node b){
        if(a.a == b.a) return a.b < b.b;
        return a.a < b.a;
    }
}q[maxn];
int pre[maxn],suf[maxn];
ll sum[maxn];
int cnt = 0;
struct Tree{
    int l,r,w;
}t[maxn*35];
int root[maxn];
void Insert(int &now,int pre,ll l,ll r,ll pos){
    t[now = ++cnt] = t[pre];
    t[now].w ++;
    if(l == r) return ;
    ll mid = (l+r)/2;
    if(pos <= mid) Insert(t[now].l,t[pre].l,l,mid,pos);
    else Insert(t[now].r,t[pre].r,mid+1,r,pos);
}
int Find(int now,ll l,ll r,ll x,ll y){
    if(x<=l && y>=r) return t[now].w;
    ll mid = (l+r)/2;
    int ans = 0;
    if(x<=mid) ans += Find(t[now].l,l,mid,x,y);
    if(y>mid) ans += Find(t[now].r,mid+1,r,x,y);
    return ans;
}
int main(){
    int T;scanf("%d",&T);
    while(T--){
        read(n);
        for(int i=1;i<=n;i++){
            read(q[i].a);
            read(q[i].b);
        }
        sort(q+1,q+1+n);
        cnt = 0;
        root[0] = 0;
        for(int i=1;i<=n;i++){
            pre[i] = Find(root[i-1],1,2e9,q[i].a,q[i].b);
            Insert(root[i],root[i-1],1,2e9,q[i].b);
        }
        cnt = 0;
        root[n+1] = 0;
        for(int i=n;i>=1;i--){
            suf[i] = Find(root[i+1],1,2e9,q[i].a,q[i].b);
            Insert(root[i],root[i+1],1,2e9,q[i].a);
        }
        ll ans = INF;
        for(int i=1;i<=n;i++)
            ans = min(ans,n-1-pre[i]-suf[i]);
        printf("%lld\n",ans);
    }
    return 0;
}

 

Guess you like

Origin blog.csdn.net/qq_43857314/article/details/111274704