codeforces round 171 div2

來源:互聯網
上載者:User

http://codeforces.com/contest/279/problem/A

A:一個螺旋線,自己畫畫圖就知道規律,給你一個點,問這個點在該螺旋線上轉了幾個彎。

思路:我是類比做的,因為資料量不大,從內往外暴力,看點是否在當前的線段上即可。

#include <iostream>#include <string.h>#include <stdio.h>using namespace std;int dir[4][2]={1,0,0,1,-1,0,0,-1};int main(){    int x,y;    scanf("%d%d",&x,&y);    int sx=0,sy=0,ans=0,d=0,len=1,tx=0,ty=0;    while(1)    {        int num=2;        while(num--)        {            //printf("%d %d\n",tx,ty);            d%=4;            sx=tx,sy=ty;            tx=sx+len*dir[d][0],ty=sy+len*dir[d][1];            if(d%2)            {                if(x==sx&&(y-sy)*(y-ty)<=0)                {                    printf("%d\n",ans);                    return 0;                }            }            else            {                if(y==sy&&((x-sx)*(x-tx))<=0)                {                    printf("%d\n",ans);                    return 0;                }            }            ans++;            d++;        }        len++;    }    return 0;}

http://codeforces.com/contest/279/problem/B

B:給你N個數,求最長的連續區間,是該區間的數字之和不大於T。

思路:乍一看覺得二分即可,其實存在更好的方法。我們從左往右掃描,設l為當前的區間的左端點,初始為1,設當前遍曆到i,則若sum[l,i]>t,則我將l++直到sum[l,i]<=t,為止,此時i-l+1為以i結尾的區間的最大值,設為tmp,我們求遍曆過程中tmp的最大值即可。時間複雜度為O(n)。

#include <iostream>#include <string.h>#include <stdio.h>#define maxn 100010using namespace std;int a[maxn];int max(int a,int b){     return a>b?a:b;}int main(){    //freopen("dd.txt","r",stdin);    int n,t,i;    scanf("%d%d",&n,&t);    for(int i=n;i>=1;i--)    scanf("%d",&a[i]);    int l=0,sum=0,ans=0;    for(i=1;i<=n;i++)    {        sum+=a[i];        if(sum<=t)        ans=max(ans,i-l);        else        {            while(sum>t)            {                sum-=a[++l];            }         ans=max(ans,i-l);        }    }    printf("%d\n",ans);    return 0;}

http://codeforces.com/contest/279/problem/C

C:給你n個數a[1]~a[n],詢問一段區間[l,r]是否滿足前面一段時非遞減的,後面一段是非遞增的。(前後兩段可為空白)

思路:設mi[i]和ma[i],分別表示以a[i]結尾,非遞減子串的左端和非遞增子串的左端。這個可以在O(N)複雜度內求解。詢問時,若mi[r]<=l或ma[i]<=l,則說明區間[l,r]為非遞減串或非遞增串,輸出YES,否則設po=mi[r],表示區間[po,r]為非遞增串,若ma[po]<=l,則說明區間[l,po]為非遞減,[po,r]為非遞增的,輸出YES,否則輸出NO。

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#define maxn 100010using namespace std;int a[maxn];int ma[maxn],mi[maxn];int main(){    //freopen("dd.txt","r",stdin);    int n,i,q;    scanf("%d%d",&n,&q);    for(i=1;i<=n;i++)    scanf("%d",&a[i]);    ma[1]=mi[1]=1;    for(i=2;i<=n;i++)    {        if(a[i]>a[i-1])        {            ma[i]=ma[i-1];            mi[i]=i;        }        else if(a[i]<a[i-1])        {            ma[i]=i;            mi[i]=mi[i-1];        }        else        {            ma[i]=ma[i-1];            mi[i]=mi[i-1];        }    }    while(q--)    {        int l,r;        scanf("%d%d",&l,&r);        if(ma[r]<=l||mi[r]<=l)        {            printf("Yes\n");        }        else        {            int po=mi[r];            if(ma[po]<=l)            printf("Yes\n");            else            printf("No\n");        }    }    return 0;}

http://codeforces.com/contest/279/problem/D

D:看了becauseofyou大神的結題報告才做出來的,代碼基本參考了becauseofyou大神的,第一個狀態壓縮DP。

把狀態用二進位表示,設狀態x的最高位的1是第i位,表示a[i]要用前面的數組合而成,第i位之前的1表示目前狀態已經儲存了a[j](0<=j<i且x的第j位為1),0表示目前狀態不確定是否儲存了a[j](0<=j<i且x的第j位為0).設dp[x]為在x狀態下所要的最小變數數。則我們要求的即為dp[1<<(n-1)]。因為每個數都是一個一個求出來的,所以再求狀態x時,它上一個狀態一定包含了前一個要求的數(即a[i-1]),且如果a[i]==a[j]+a[k](0<=j,k<i),表示a[i]是由a[j]和a[k]轉移來的,所以上一個狀態一定以儲存了a[j]和a[k],所以狀態轉移方程就出來了。

還有一個要注意的一點,設num為狀態x用二進位表示中1的個數,則dp[x]至少為num,這個由狀態x的意義即可理解。

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>#define inf 2100000000using namespace std;int a[25],pow[23];int dp[1<<23],n;void init(){    memset(dp,-1,sizeof(dp));    pow[0]=1;    for(int i=1;i<23;i++)    pow[i]=2*pow[i-1];}int min(int a,int b){    return a<b?a:b;}int max(int a,int b){    return a>b?a:b;}int dfs(int x){    if(dp[x]!=-1)    return dp[x];    int num=__builtin_popcount(x);    int ans=inf,tmp;    for(int i=n-1;i>=0;i--)    {        if(x&pow[i])        {            int tt=(x^pow[i])|pow[i-1];            for(int j=i-1;j>=0;j--)            {                for(int k=j;k>=0;k--)                {                    if(a[i]==a[j]+a[k])                    {                        tmp=dfs(tt|pow[j]|pow[k]);                        if(tmp!=inf)                        ans=min(ans,max(tmp,num));                    }                }            }            break;        }    }    dp[x]=ans;    return ans;}int main(){    //freopen("dd.txt","r",stdin);    int i;    init();    scanf("%d",&n);    for(i=0;i<n;i++)    scanf("%d",&a[i]);    dp[1]=1;    int ans=dfs(pow[n-1]);    if(ans==inf)    ans=-1;    printf("%d\n",ans);    return 0;}

http://codeforces.com/contest/279/problem/E

E:給你一個用二進位表示的數a[1]~a[n],求用最少的 2^k和-2^k形式的數,它們的和等於所給的數。

思路:貪心也可以,不過我是DP做的,還是挺簡單的。一個簡單的結論就是對於所用的數的k各不相同。

設dp[i]表示最後i位元所需要的最小值,我們從後往前遍曆。

當a[i]=1,則我們可以直接加上2^i,即dp[i]=dp[i+1],或者我們可以用2^(i+1)-2^j(0<=j<i)使得第i位為1,但是這樣還沒完,我們還要加上dp[n-j+1],並且對於[i,n-j]中的0,我們還要用-2^x(i<x<=n-j且a[x]==0),我們要使得所取得數最小,就要使得dp[n-j+1]+2+num(num為區間[i,n-j]中0的個數)最小,我們設這個值對於不同的位置x為w[x],這似乎需要O(n^2)的複雜度,其實不然,其實具觀察可發現,如果對於位置po最小,事實上,若a[i]=1,num不變,則還是w[po]最小。

若a[i]=0,則num++,w[po]++,這時候只有w[i]可能小於w[po],我們比較一下更新即可。最後複雜度可以達到O(n)。

(表達能力屎一樣啊,說的一點都不明白,還是看代碼吧)

#include <iostream>#include <string.h>#include <stdio.h>#include <algorithm>using namespace std;char str[1000010];int dp[1000010];int min(int a,int b)  {    return a>b?b:a;    }int main(){   // freopen("dd.txt","r",stdin);  int i,tmp=0;  scanf("%s",str+1);  int n=strlen(str+1);  dp[n]=str[n]-'0';  for(i=n-1;i>=1;i--)    {      if(str[i]=='1')        dp[i]=min(dp[i+1]+1,tmp+2);      else        {          tmp++;          dp[i]=dp[i+1];          tmp=min(tmp,dp[i]);          }      }  printf("%d\n",dp[1]);  return 0;}



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.