2015多校7

2015 Multi-University Training Contest 7

Start Time : 2015-08-11 12:00:00    End Time : 2015-08-11 17:00:00
Contest Type : Private   Contest Status : Ended
Current Server Time : 2015-08-11 17:47:07
Solved Pro.ID Title Ratio(Accepted / Submitted)
  1001 Game On the Tree 4.44%(2/45)
  1002 Tree Maker 18.75%(21/112)
  1003 Hotaru's problem 10.60%(160/1509)
  1004 Segment Game 13.07%(52/398)
  1005 The shortest problem 26.38%(607/2301)
  1006 Tetris 30.34%(44/145)
  1007 Gray code 31.25%(456/1459)
  1008 Convex Polygon 18.18%(4/22)
  1009 Root 3.41%(7/205)
  1010 Leader in Tree Land 28.74%(50/174)
  1011 Mahjong tree 19.25%(257/1335)

 

 

 

Pro.ID Title Author Source (AC/Submit)Ratio
5369 Game On the Tree   2015 Multi-University Training Contest 7 (12/54)22.22%
5370 Tree Maker   2015 Multi-University Training Contest 7 (46/118)38.98%
5371 Hotaru's problem   2015 Multi-University Training Contest 7 (593/1653)35.87%
5372 Segment Game   2015 Multi-University Training Contest 7 (270/965)27.98%
5373 The shortest problem   2015 Multi-University Training Contest 7 (481/948)50.74%
5374 Tetris   2015 Multi-University Training Contest 7 (97/217)44.70%
5375 Gray code   2015 Multi-University Training Contest 7 (361/612)58.99%
5376 Convex Polygon   2015 Multi-University Training Contest 7 (22/70)31.43%
5377 Root   2015 Multi-University Training Contest 7 (31/102)30.39%
5378 Leader in Tree Land   2015 Multi-University Training Contest 7 (133/351)37.89%
5379 Mahjong tree   2015 Multi-University Training Contest 7 (341/1114)30.61%

 

HDU5371php

給一個長度爲n的序列,求最長的連續子序列長度。符合:ios

能夠分紅3部分 ,第一部分與第三部分同樣,第一部分與第二部分互爲轉置。算法

如2 3 4 4 3 2 2 3 4 數組

用manacher算法O(n)時間算出以s[i]和s[i+1]爲中心的迴文串的半徑f[i],只要在f[i]的半徑範圍[i-f[i],i+f[i]-1]內有f[j]>|j-i|就說明存在符合要求的串,遍歷求最大值便可ide

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int s[220220];
int p[220220];
int f[220220];
int main()
{
    int T;
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        int len;
        scanf("%d",&len);
        for(int i=0;i<len;i++)
        {
            s[i*2]=-1;
            scanf("%d",&s[i*2+1]);
        }
        len*=2;
        s[len]=-1;
        p[0]=1;
        p[1]=2;
        int maxlen=1;
        int id=1;
        for(int i=2;i<=len;i++)
        {
            if(i>maxlen)
            {
                int k=1;
                while(i-k>=0&&i+k<=len&&s[i-k]==s[i+k])k++;
                p[i]=k;
                maxlen=min(p[i]+i-1,len);
                id=i;
            }
            else
            {
                if((2*id-i)-p[2*id-i] != id-p[id])
                    p[i]=min(p[2*id-i],maxlen-i+1);
                else
                {
                    int k=p[2*id-i];
                    while(i-k>=0&&i+k<=len&&s[i-k]==s[i+k])k++;
                    p[i]=k;
                    maxlen=min(p[i]+i-1,len);
                    id=i;
                }
            }
        }
        for(int i=0;i<=len;i+=2)
        {
            f[i/2]=(p[i]-1)/2;
        }
        int ans=0;
        len/=2;
        for(int i=0;i<len;i++)
        {
            for(int j=ans+1;j<=f[i];j++)
            {
                if(f[i+j]>=j)ans=max(ans,j);
            }
        }
        printf("Case #%d: %d\n",ca,ans*3);
    }
    return 0;
}
View Code

 

HDU5372spa

有一個數軸,每次往數軸上放一個線段[a,b]或者刪除一個線段(每一個線段獨立)(id),在放前詢問[a,a+i]內有多少完整的線段,即以前放的線段有多少是徹底在[a,b]的範圍內的code

[a,b]中b=a+ind,ind爲放線段的個數(不包括刪除) , id爲第id個放入的線段。blog

用兩個樹狀數組分別維護 <=a ,<=b 的個數,詢問時求出左邊大於等於當前左端點的線段數目和右邊大於當前右端點線段數目,求差便可。ci

數據須要離散化get

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define low(x) (x&(-x))
#define maxn 400040
struct ss
{
    int op,a,b;
}arr[maxn/2],add[maxn/2];
int cleft[maxn],cright[maxn];
int s[maxn];
int addleft(int i,int val)
{
    while(i<maxn)
    {
        cleft[i]+=val;
        i+=low(i);
    }
}
int getleft(int i)
{
    int sum=0;
    while(i>0)
    {
        sum+=cleft[i];
        i-=low(i);
    }
    return sum;
}
int addright(int i,int val)
{
    while(i<maxn)
    {
        cright[i]+=val;
        i+=low(i);
    }
}
int getright(int i)
{
    int sum=0;
    while(i>0)
    {
        sum+=cright[i];
        i-=low(i);
    }
    return sum;
}
int main()
{
    int n;
    int ca=1;
    while(~scanf("%d",&n))
    {
        memset(cleft,0,sizeof(cleft));
        memset(cright,0,sizeof(cright));
        int ind=0;
        int ad=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d",&arr[i].op,&arr[i].a);
            arr[i].b=arr[i].a+ad+1;
            s[ind++]=arr[i].a;
            s[ind++]=arr[i].b;
            if(!arr[i].op)
            {
                add[ad++]=arr[i];
            }
        }
        sort(s,s+ind);//paixu
        ind=unique(s,s+ind)-s;//quchong

        printf("Case #%d:\n",ca++);
        for(int i=0;i<n;i++)
        {
           if(!arr[i].op){
                int a=lower_bound(s,s+ind,arr[i].a)-s+1;//lisan
                int b=lower_bound(s,s+ind,arr[i].b)-s+1;
             //   printf("add: %d %d %d\n",arr[i].op,a,b);
                int left=getleft(maxn)-getleft(a-1);
                int right=getright(maxn)-getright(b);
                printf("%d\n",max(0,left-right));
                addleft(a,1);
                addright(b,1);
           }
           else
           {
               int id=arr[i].a-1;

               int a=lower_bound(s,s+ind,add[id].a)-s+1;//lisan
               int b=lower_bound(s,s+ind,add[id].b)-s+1;
             // printf("delete: id=%d %d %d\n",id,a,b);
               addleft(a,-1);
               addright(b,-1);
           }
        }
    }
    return 0;
}
/*
6
0 1
0 0
1 2
0 0
1 3
0 0

ans:
0
1
1
1
*/
View Code

 

HDU5373

求n通過t次迭代變換後是否能整出11,n->n+n的每位數之和 爲一次變換

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
int s,n,t;
int sum,p;
void run(int n)
{
    p=1;
    while(n)
    {
        p*=10;
        sum+=n%10;
        n/=10;
    }
}
int main()
{
    int ca=1;
    while(~scanf("%d%d",&n,&t))
    {
        if(n==-1&&t==-1)
            break;
        sum=0;
        int s=n;
        int ans=0;
        t++;
        while(t--)
        {
            run(s);
            ans=(ans*p+s)%11;
            s=sum;
        }
        if(ans%11==0)printf("Case #%d: Yes\n",ca++);
        else printf("Case #%d: No\n",ca++);
    }
    return 0;
}
View Code

 

HDU5375

gray碼是由相鄰二進制碼兩兩抑或獲得的,第一個gray碼就是第一個二進制碼

當前的狀態只和前一狀態有關,dp分類討論便可

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
int dp[200020][2];
char s[200020];
int a[200020];
int main()
{
    int T;
    scanf("%d",&T);
    s[0]='0';
    for(int ca=1;ca<=T;ca++)
    {
        memset(dp,0,sizeof(dp));
        scanf("%s",s+1);
        int n=strlen(s+1);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<=n;i++)
        {
            if(s[i]=='0')
            {
                if(s[i-1]=='0')dp[i][0]=dp[i-1][0];
                else if(s[i-1]=='1')dp[i][0]=dp[i-1][1]+a[i];
                else dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);
            }
            else if(s[i]=='1')
            {
                if(s[i-1]=='0')dp[i][1]=dp[i-1][0]+a[i];
                else if(s[i-1]=='1')dp[i][1]=dp[i-1][1];
                else dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);
            }
            else{
                if(s[i-1]=='0')dp[i][0]=dp[i-1][0];
                else if(s[i-1]=='1')dp[i][0]=dp[i-1][1]+a[i];
                else dp[i][0]=max(dp[i-1][0],dp[i-1][1]+a[i]);

                if(s[i-1]=='0')dp[i][1]=dp[i-1][0]+a[i];
                else if(s[i-1]=='1')dp[i][1]=dp[i-1][1];
                else dp[i][1]=max(dp[i-1][0]+a[i],dp[i-1][1]);
            }
        }
        printf("Case #%d: %d\n",ca,max(dp[n][0],dp[n][1]));
    }

    return 0;
}
View Code

 

HDU5379

給定一棵n個節點的數,和一組編號1.2.3...n的麻將牌,要求:

1.每一個節點只能放一個麻將牌

2.父親的全部直接兒子上面的麻將牌要連續

3.全部子樹上面的麻將牌要連續

求放置的方法數。

題目就是求一個連續序列能分紅k段的方法數目,bfs求解。對於每棵子樹而言,

1.只要有兒子節點,方法數*2  (因爲是一棵樹,鄰接表中v[i].size()>1就說明有兒子。

2.有孫子的兒子節點最多隻能有兩個。

3.若是有孫子的兒子節點>=1個,方法數*2

4.沒有孫子的兒子節點數爲k個,方法數*k!

5.數據範圍longlong

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define maxn 100010
#define mod 1000000007
vector<int>s[maxn];
int n;
int v[maxn];
ll ans;
void bfs()
{
    queue<int>q;
    memset(v,0,sizeof(v));
    while(!q.empty())q.pop();
    q.push(0);
    ans=1;
    v[0]=1;
    while(!q.empty())
    {
        int fa=q.front();
        q.pop();
        int num=0;
        int sig=0;
        for(int i=0;i<s[fa].size();i++)
        {
            int su=s[fa][i];
            if(!v[su])
            {
                v[su]=1;
                if(s[su].size()>1)num++;
                else sig++;
                q.push(su);
            }
        }
        if(num>2){
            ans=0;
            return;
        }
        if(num!=0)ans=(ans*2)%mod;
        for(int i=1;i<=sig;i++)
        {
            ans=(ans*i)%mod;
        }
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    for(int ca=1;ca<=T;ca++)
    {
        scanf("%d",&n);
        for(int i=0;i<=n;i++)s[i].clear();
        int u,v;
        s[0].push_back(1);
        s[1].push_back(0);
        for(int i=0;i<n-1;i++)
        {
            scanf("%d%d",&u,&v);
            s[u].push_back(v);
            s[v].push_back(u);
        }
        bfs();
        printf("Case #%d: %lld\n",ca,ans);
    }
    return 0;
}
View Code
相關文章
相關標籤/搜索