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

Codeforces Round #310 (Div. 2)

max 工作 clas pop pla 完成 include gif sort

Problem A:

題目大意:給你一個由0,1組成的字符串,如果有相鄰的0和1要消去,問你最後還剩幾個字符。

寫的時候不想看題意直接看樣例,結果我以為是1在前0在後才行,交上去錯了。。後來仔細

看了看,哎。以後不能自以為是啊。

技術分享
#include<bits/stdc++.h>
using namespace std;
const int N=2*1e5+2;
char s[N];
bool vis[N];
int main()
{
    int n;
    scanf("%d%s",&n,s);
    int cnt=n;
    int cnt1=0,cnt0=0;
    
for(int i=0;i<n;i++) { if(s[i]==0) cnt0++; else cnt1++; } printf("%d\n",max(cnt0-cnt1,cnt1-cnt0)); }
View Code

Problem B:

題目大意:給你n個一排的齒輪,每個齒輪有編號(0->n-1)的鋸齒,問你能不能轉動第一個輪子,

使其向上的鋸齒依次為,0,1,2,3...n-1。水題,你就把第一個齒輪轉到0的次數記錄下來,第偶數

個加上,奇數個減去,判斷一下。

技術分享
#include<bits/stdc++.h>
using
namespace std; const int N=1005; int a[N]; int main() { int n; cin>>n; for(int i=0;i<n;i++) scanf("%d",&a[i]); int cnt=n-a[0]; //printf("%d\n",cnt); for(int i=1;i<n;i++) { if(i%2) { if((a[i]-cnt+n)%n!=i) { puts(
"No"); return 0; } } else { if((a[i]+cnt+n)%n!=i) { puts("No"); return 0; } } } puts("Yes"); return 0; }
View Code

Problem C:

題目大意:給你n個編號1->n的杯子,編號代表了它們的大小,只有大的能套在小的上,現在

給你這些杯子現在的情況,讓你把他變成1<-2<-3<-4....<-n這種形式需要操作幾次。簡單模擬

一下就好了。

技術分享
#include<bits/stdc++.h>
using namespace std;
int n,k,ans,st;
int pre[100005];
void Find(int x)
{
    if(pre[x]!=x)
    {
        Find(pre[x]);
        ans++;
        pre[x]=x;
    }
}
void judge(int now,int p)
{
    if(now==p+1 || p==-1)
    {
        st=now;
        judge(pre[now],now);
    }
}
int main()
{
    cin>>n>>k;
    for(int i=1;i<=n;i++) pre[i]=i;
    for(int i=1;i<=k;i++)
    {
        int m;
        scanf("%d",&m);
        int p=-1;
        while(m--)
        {
            int g;
            scanf("%d",&g);
            if(p!=-1)
            {
                pre[p]=g;
            }
            p=g;
        }
    }
    ans=0;
    st=1;
    judge(1,-1);
    Find(st);
    for(int i=st+1;i<=n;i++)
    {
        Find(i);
        pre[i-1]=i;
        ans++;
    }
    cout<<ans<<endl;
    return 0;
}
View Code

Problem D:

題目大意:有n個排成以行的小道他們的範圍分別是(l[i]->r[i])且l[i+1]>r[i],現在有m個長度為b[i]的橋

兩個島能加上長度為a的橋當且僅當 r[i+1]-l[i]>=a>=l[i+1]-r[i]。問你能不能完成這個工作。

這個題很顯然,可以轉換成這個問題:有n-1個區間,m個數,每個數最多只能用一次,第i個數只

要能被第j個區間包含,那麽這個數就可以放入這個區間內。求出,當所有區間裏都恰有一個數時的情況。

我寫的時候一直在想固定最大範圍和最小範圍來貪心,用橋去滿足他們,這種方法是不對的。

思路:我們可以將區間按按l排序,橋按長度排序,然後將當前滿足 r>=a>=l 的區間都加到優先隊列

裏面,每次取出r最小的區間,這個橋就搭在這個區間上,為什麽呢,因為對於優先隊列裏面的區間

來說,當前及以後的橋都滿足,len[i]>=l 所以可以不用考慮區間的l,這樣我們顯然就可以貪心地取

r小的區間。

技術分享
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=2*1e5+5;
struct node
{
    ll mx,mn;
    int id;
    bool operator <(const node&t) const
    {
        return mx>t.mx;
    }
}w[N];
bool cmp(node a,node b)
{
    return a.mn<b.mn;
}
struct num
{
    ll v;
    int id;
    bool operator <(const num &t)const
    {
        return v<t.v;
    }
}a[N];
ll ans[N];
int n,m;
int main()
{
    cin>>n>>m;
    ll pl=-1,pr=-1;
    for(int i=0;i<n;i++)
    {
        ll l,r;
        scanf("%I64d%I64d",&l,&r);
        if(pl!=-1)
        {
            //printf("%d**\n",i);
            w[i].mx=r-pl;
            w[i].mn=l-pr;
            w[i].id=i;
        }
        pl=l,pr=r;
    }
    for(int i=1;i<=m;i++)
    {
        scanf("%I64d",&a[i].v);
        a[i].id=i;
    }
    sort(a+1,a+1+m);
    sort(w+1,w+n,cmp);
    //for(int i=1;i<=m;i++) printf("%I64d ",a[i].v);
    //puts("");
    //for(int i=1;i<n;i++) printf("[%I64d,%I64d] ",w[i].mn,w[i].mx);
    priority_queue<node> Q;
    int cnt=0;
    for(int i=1,j=1;i<=m;i++)
    {
        while(w[j].mn<=a[i].v && a[i].v<=w[j].mx && j<n)
        {
            Q.push(w[j]);
            j++;
        }
        if(Q.empty()) continue;
        node now=Q.top();Q.pop();
        if(a[i].v>now.mx)
        {
            puts("No");
            return 0;
        }
        ans[now.id]=a[i].id;
        cnt++;
    }
    //printf("%d\n",cnt);
    if(cnt<n-1)
    {
        puts("No");
        return 0;
    }
    puts("Yes");
    for(int i=1;i<n;i++) printf("%I64d%c",ans[i],i==n-1?\n :  );
    return 0;
}
View Code

problem E:

題意:

有一塊n*n大小的巧克力,n<=1e9。現在進行操作,每次都從反對角線上選擇一點,然後往上或往左一直吃,

每當到達巧克力邊緣或者下一塊已經被吃了,則停止。問你每次操作能吃到幾塊巧克力。

思維題,感覺挺難想到了,還是我太菜了。。

思路:我們考慮從j列往上吃巧克力,吃掉的個數受什麽影響呢,肯定不受<j的列印象,對它有直接影響的就

他右邊第一個有操作的點,如果這個點的操作時向左吃,則從j列向上吃只能吃到有操作點的那一行,如果右邊

第一個有操作的點是向上吃,則j列吃的和它一樣。

技術分享
#include<bits/stdc++.h>
using namespace std;
map<int,int> u,l;
int n,q;
int main()
{
    cin>>n>>q;
    while(q--)
    {
        int x,y;
        char s[3];
        scanf("%d%d%s",&x,&y,s);
        map<int,int>::iterator p;
        if(s[0]==U)
        {
            int ans=0;
            p=u.lower_bound(x);
            if(u.count(x))
            {
                puts("0");
                continue;
            }
            if(p==u.end()) ans=y;
            else ans=y-(p->second);
            printf("%d\n",ans);
            l[y]=x;
            u[x]=y-ans;
        }
        else
        {
            int ans=0;
            p=l.lower_bound(y);
            if(l.count(y))
            {
                puts("0");
                continue;
            }
            if(p==l.end()) ans=x;
            else ans=x-(p->second);
            printf("%d\n",ans);
            u[x]=y;
            l[y]=x-ans;
        }
    }
    return 0;
}
View Code

Codeforces Round #310 (Div. 2)