1. 程式人生 > >Codeforces Round #452 (Div. 2)

Codeforces Round #452 (Div. 2)

spl truct eps cto 技術 ase n) 隊列 給定

A:水題

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define
pii pair<int,int> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=200000+10,maxn=90000+10,inf=0x3f3f3f3f; int main() { int n; scanf("%d",&n); int one=0,two=0;
for(int i=0;i<n;i++) { int x; scanf("%d",&x); if(x==1)one++; else two++; } int ans=0; ans+=min(two,one); one-=min(two,one); printf("%d\n",ans+one/3); return 0; } /******************** ********************/
A

B:也很水,不過我看很多人被kack了,可能處理有點麻煩,我是直接轉化成字符串然後匹配

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pii pair<int,int>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=200000+10,maxn=90000+10,inf=0x3f3f3f3f;

string s="312831303130313130313031312831303130313130313031312831303130313130313031312931303130313130313031312831303130313130313031312831303130313130313031312831303130313130313031";
int main()
{
    fio;
    int n;
    cin>>n;
    string p="";
    for(int i=0;i<n;i++)
    {
        string te;
        cin>>te;
        p+=te;
    }
    for(int i=0;i<s.size();i++)
    {
        if(s.substr(i,p.size())==p)
        {
            cout<<"YES\n";
            return 0;
        }
    }
    cout<<"NO\n";
    return 0;
}
/********************

********************/
B

C:有一個n,1到n,分兩組,要求和的差最小,直接從大到小貪心

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pil pair<int,ll>
#define pii pair<int,int>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=200000+10,maxn=90000+10,inf=0x3f3f3f3f;

int main()
{
    int n;
    scanf("%d",&n);
    ll sum=(ll)(1+n)*n/2;
    if(sum%2==0)puts("0");
    else puts("1");
    sum/=2;
    vector<int>v;
    for(int i=n;i>=1;i--)
    {
        if(sum-i>=0)
        {
            sum-=i;
            v.pb(i);
        }
    }
    printf("%d ",v.size());
    for(int i=0;i<v.size();i++)
        printf("%d ",v[i]);
    puts("");
    return 0;
}
/********************

********************/
C

D:題意:給一個n,求從1到n中選兩個數,加起來末尾的9最多的情況數

題解:先找在5,50,500.。。。那個區間裏,然後枚舉,末尾9的個數相同的數,然後直接套公式即可

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pii pair<int,int>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=40000+10,maxn=200000+10,inf=0x3f3f3f3f;

ll p[20];
int main()
{
    ll n;
    scanf("%lld",&n);
    if(n<5)
    {
        printf("%lld\n",(n*n-n)/2);
        return 0;
    }
    p[0]=5;
    for(ll i=1;i<=10;i++)p[i]=p[i-1]*10;
    int id=upper_bound(p,p+10,n)-p;
    --id;
    ll ans=0;
    for(ll i=p[id]*2-1;i<p[id+1]*2-1;i+=p[id]*2)
    {
        if(2*n<=i)break;
      //  cout<<i<<endl;
        ans+=min(i-1,n)-(i+1)/2+1;
        //cout<<ans<<endl;
    }
    printf("%lld\n",ans);
    return 0;
}
/********************

********************/
D

E:題意:n個數,每次刪除最左邊的連續相同數字最多的那個區間,問要刪幾次;

題解:優先隊列維護,先按連續數字相同排序,其次按坐標排序,然後對於每次操作,看刪除這個區間之後前後會不會連起來,會的話就把這個合並區間加入隊列原來的兩個刪掉,否則不管

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pii pair<int,int>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=200000+10,maxn=200000+10,inf=0x3f3f3f3f;

struct seg{
    int l,r,v,num;
    bool operator <(const seg &rhm)const{
        if(num==rhm.num)return l>rhm.l;
        return num<rhm.num;
    }
}s[N*10];
priority_queue<seg>q;
map<int,int>ma[N];
int lrtoid[N];
int pre[N],last[N];
int Hash[N];
int main()
{
    int n,sz=0,id=0,cnt=0;
    scanf("%d",&n);
    scanf("%d",&s[++id].v);
    Hash[cnt++]=s[id].v;
    pre[s[id].l]=-1;
    s[id].l=s[id].r=s[id].num=1;
    for(int i=2;i<=n;i++)
    {
        int x;
        scanf("%d",&x);
        if(x==s[id].v)
        {
            s[id].r++,s[id].num++;
        }
        else
        {
            lrtoid[s[id].l]=lrtoid[s[id].r]=id;
            pre[s[id].r+1]=s[id].r;
            last[s[id].r]=s[id].r+1;
            Hash[cnt++]=s[id].v;
            q.push(s[id]);
            ++id;
            s[id].v=x,s[id].l=s[id].r=i,s[id].num=1;
        }
    }
    lrtoid[s[id].l]=lrtoid[s[id].r]=id;
    last[s[id].r]=-1;
    Hash[cnt++]=s[id].v;
    q.push(s[id]);
    sort(Hash,Hash+cnt);
    cnt=unique(Hash,Hash+cnt)-Hash;
    for(int i=1;i<=id;i++)s[i].v=lower_bound(Hash,Hash+cnt,s[i].v)-Hash;
//    while(!q.empty())
//    {
//        seg s=q.top();
//        q.pop();
//        printf("%d %d %d %d\n",s.l,s.r,s.v,s.num);
//    }
    int ans=0;
    while(!q.empty())
    {
        seg ss=q.top();
        q.pop();
      //  printf("%d %d %d %d\n",ss.l,ss.r,ss.v,ss.num);
        if(ma[ss.l][ss.r])continue;
        ans++;
        if(pre[ss.l]==-1&&last[ss.r]==-1)break;
        else if(pre[ss.l]==-1&&last[ss.r]!=-1)pre[last[ss.r]]=-1;
        else if(pre[ss.l]!=-1&&last[ss.r]==-1)last[pre[ss.l]]=-1;
        else
        {
            int id1=lrtoid[pre[ss.l]],id2=lrtoid[last[ss.r]];
            if(s[id1].v==s[id2].v)
            {
                ma[s[id1].l][s[id1].r]=ma[s[id2].l][s[id2].r]=1;
                s[++id].l=s[id1].l,s[id].r=s[id2].r,s[id].num=s[id1].num+s[id2].num,s[id].v=s[id1].v;
                lrtoid[s[id].l]=lrtoid[s[id].r]=id;
                q.push(s[id]);
            }
            else
            {
                last[s[id1].r]=s[id2].l;
                pre[s[id2].l]=s[id1].r;
            }
        }
    }
    printf("%d\n",ans);
    return 0;
}
/********************

********************/
E

F:題意:一個字符串,m次操作,每次操作刪除區間l到r之間的所有字符c,求完成操作後的字符串

題解:對於每一種字符維護一個set,插入坐標,每次刪除就刪掉該區間對應坐標,剩下的問題就是如何將給定的區間映射到原區間,我們采用樹狀數組維護,每次刪除該點時,就在樹狀數組裏-1,映射時用二分,復雜度O(nloglogn)

技術分享圖片
#include<bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define mod 1000000007
#define C 0.5772156649
#define ls l,m,rt<<1
#define rs m+1,r,rt<<1|1
#define pii pair<int,int>
#define ull unsigned long long
#define base 1000000000000000000
#define fio ios::sync_with_stdio(false);cin.tie(0)

using namespace std;

const double g=10.0,eps=1e-12;
const int N=200000+10,maxn=200000+10,inf=0x3f3f3f3f;

int sum[N],n,m;
void add(int x,int v)
{
    while(x<N)
    {
        sum[x]+=v;
        x+=x&(-x);
    }
}
int query(int x)
{
    int ans=0;
    while(x>0)
    {
        ans+=sum[x];
        x-=x&(-x);
    }
    return ans;
}
int change(int x)
{
    int l=0,r=n+1;
    while(l<r-1)
    {
        int m=(l+r)>>1;
        if(query(m)>=x)r=m;
        else l=m;
    }
    return r;
}
set<int>s[123];
bool vis[N];
int main()
{
    fio;
    string p;
    cin>>n>>m>>p;
    for(int i=0;i<n;i++)
    {
        add(i+1,1);
        s[p[i]].insert(i+1);
    }
    while(m--)
    {
        int l,r;
        string te;
        cin>>l>>r>>te;
        l=change(l),r=change(r);
        //cout<<l<<" "<<r<<endl;
        int id=te[0];
        auto x=s[id].lower_bound(l);
        for(;x!=s[id].end();)
        {
            if((*x)>r)break;
            //cout<<(*x)<<"+++++";
            add((*x),-1);
            s[id].erase(x++);
        }
//        cout<<endl;
//        for(int i=1;i<=n;i++)cout<<query(i)<<" ";
//        cout<<endl;
    }
    for(int i=0;i<123;i++)
        for(auto x:s[i])
            vis[x-1]=1;
    for(int i=0;i<n;i++)
        if(vis[i])
            cout<<p[i];
    cout<<"\n";
    return 0;
}
/********************
10 4
agtFrgF4aF
2 5 g
4 9 F
1 5 4
1 7 a
********************/
F

Codeforces Round #452 (Div. 2)