1. 程式人生 > 實用技巧 >[題解]AtCoder Beginner Contest 174

[題解]AtCoder Beginner Contest 174

AtCoder Beginner Contest 174

閒來無事摸了一場ABC

A

按題意模擬即可 \(\leq 30\)輸出 Yes 否則 No

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a) & -(a))
#define clean(a, b) memset(a, b, sizeof(a))
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 9;

int _;

//========================================================================

//========================================================================
int main()
{
    int n;
    scanf("%d",&n);
    if(n>=30) puts("Yes");
    else puts("No");
    
    return 0;
}

B

給你一些座標 問有多少座標與原點距離小於\(d\)
怕有誤差可以把開根號換成\(d*d\) 記得開long long
(大於小於看反了 慢了幾分鐘)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a) & -(a))
#define clean(a, b) memset(a, b, sizeof(a))
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 9;

int _;

//========================================================================

//========================================================================
int main()
{
    ll n,d,x,y,cnt=0;
    scanf("%lld%lld",&n,&d);
    d=d*d;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld%lld",&x,&y);
        if(d>=x*x+y*y) cnt++;
    }
    printf("%lld\n",cnt);
    
    return 0;
}

C

有一個序列\(7,77,777,7777……\)
給你一個數k,問k的倍數是否有可能是上述序列中的元素
如果是,請輸出最小是幾個七

貌似可以暴力做,最大就是\(k\)\(7\)
首先只有尾數是\(1,3,7,9\)的數的倍數結尾有可能是\(7\)
其次 有\(1\leq i\leq k\),如果\(i\)\(7\% k==0\)那麼輸出i就可以了,否則-1
要用到高精取模 學到了學到了
我的程式碼還要特判\(1\)\(7\) 可能是寫法問題

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a) & -(a))
#define clean(a, b) memset(a, b, sizeof(a))
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 9;

int _;

//========================================================================

//========================================================================
int main()
{
    int n,sum=7;
    scanf("%d",&n);
    if(n%2==0) 
    {
        printf("-1\n");
        return 0;
    }
    if(n==1||n==7) 
    {
        printf("1\n");
        return 0;
    }
    for(int i=1;i<=n;i++)
    {
        if(sum==0) 
        {
            printf("%d\n",i);
            return 0;
        }
        sum=(sum*10+7)%n;
    }
    printf("-1\n");
    return 0;
}

D

只可以通過把w變成R或者把R變成W或者交換RW使得W左邊沒有R
那麼這三種情況肯定有一個最優的,取最小就可
(但事實上好像只判斷第三種就可以)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a) & -(a))
#define clean(a, b) memset(a, b, sizeof(a))
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int maxn = 2e5 + 9;

int _;

//========================================================================
char s[maxn];
//========================================================================
int main()
{
    int n;
    scanf("%d",&n);
    scanf("%s",s);
    int num1=0,num2=0;
    for(int i=0;i<n;i++)
    {
        if(s[i]=='W') num1++;
        else num2++;
    }
    int cnt=0;
    for(int i=0;i<n;i++)
    {
        if(i<num2) 
        {
            if(s[i]!='R') cnt++;
        }
        else 
        {
            if(s[i]!='W') cnt++;
        } 
    }
    printf("%d\n",min(num1,min(num2,cnt/2)));
    return 0;
}

E

給你一些長度的木頭,只可以砍k次,使得砍完的木頭們的最高高度最矮,輸出最高高度
想挺久的不知道怎麼分配
後來突然想到 可以二分答案做,如果高度很小,那就是不成立的,如果高度很高,那一定成立,存在單調性,根據題意,求的就是滿足條件的最小值

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a) & -(a))
#define clean(a, b) memset(a, b, sizeof(a))
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 9;

int _;

//========================================================================
int a[maxn],n,k;
bool check(int now)
{
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        sum+=(a[i]-1)/now;
    }
    if(sum<=k) return 1;
    return 0;
}
int two_points(int minn,int maxx)
{
    int l=minn,r=maxx,mid,ans;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(mid)) r=mid-1;
        else l=mid+1;
        ans=r+1;
    }
    return ans;
}
//========================================================================
int main()
{
    int maxx=0;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        maxx=max(maxx,a[i]);
    }
    int ans=two_points(1,maxx);
    printf("%d\n",ans);
    return 0;
}

F

給你一個序列,每個數字代表一種顏色
有q組詢問 每組詢問問在[l,r]內有多少種不同的顏色
這題很眼熟欸,洛谷原題 HH的項鍊 樹狀陣列or線段樹

首先對於[l,r]每個顏色最有用的就是在這個區間內最靠右的位置,那麼每個顏色我們只保留最右邊的那個,然後再進行區間和的查詢
實現的方式也很簡單,我們先記下來對於當前位置,與他相同顏色的前一個位置是在哪裡,把他這個位置的值-1,把當前位置的值+1(對於與他相同顏色的前一個位置存在,那麼那個位置的數值一定加過了,如果不存在,就不加)
先對q組詢問離線處理,按r排序可以降低複雜度,每次對於x[i-1].r到x[i].r,更新這個區間內的顏色(把當前位置顏色相同是上一個位置的值-1,把當前位置的值+1)
更新過後取sum(r)-sum(l-1)即可

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define lowbit(a) ((a) & -(a))
#define clean(a, b) memset(a, b, sizeof(a))
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int maxn = 2e6 + 9;

int _;

//========================================================================
int c[maxn],a[maxn],last[maxn],pre[maxn],n,ans[maxn];
struct node
{
    int l,r,num;
}x[maxn];
int cmp(node a,node b)
{
    if(a.r==b.r) return a.l<b.l;
    return a.r<b.r;
}
void update(int x,ll y,int n)///One point update
{
    for(int i=x; i<=n; i+=lowbit(i))
        c[i] += y;
}
ll get_sum(int x)///Interval query
{
    ll ans = 0;
    for(int i=x; i; i-=lowbit(i))
        ans += c[i];
    return ans;
}
//========================================================================
int main()
{
    int q;
    scanf("%d%d",&n,&q);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        if(last[a[i]])
        {
            pre[i]=last[a[i]];
            last[a[i]]=i;
        }
        else 
        {
            pre[i]=maxn+1;
            last[a[i]]=i;
        }
    }
    for(int i=1;i<=q;i++)
    {
        scanf("%d%d",&x[i].l,&x[i].r);
        x[i].num=i;
    }
    sort(x+1,x+1+q,cmp);
    int j=1;
    for(int i=1;i<=q;i++)
    {
        for(;j<=x[i].r;j++)
        {
            update(pre[j],-1,n);
            update(j,1,n);
        }
        ans[x[i].num]=get_sum(x[i].r)-get_sum(x[i].l-1);
    }
    for(int i=1;i<=q;i++) printf("%d\n",ans[i]);
    return 0;
}