1. 程式人生 > >多校 2009 4

多校 2009 4

ans algorithm one ostream space del while scan 多少

A dp

吃了 (x,y)的豆子 就不能吃x-1 x+1 行 還有 (x,y-1),(x,y+1) 的豆子

求最大 果然是菜菜 第1 先想怎麽求得一行的最大的 ->>>>> 就是求最大不連續的和dp[i]=max(dp[i-1],dp[i-2]+w[i]);

那麽整個矩陣呢 把上面處理出來每一行最大的 求一個最大不連續的和

技術分享
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<math.h>
#include
<queue> using namespace std; #define MAXN 200010 #define inf 1000000007 #define ll long long int z[MAXN]; int dp[MAXN]; int sum[MAXN]; int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) scanf(
"%d",&z[j]); dp[0]=0; dp[1]=z[1]; int mx=dp[1]; for(int j=2;j<=m;j++) { dp[j]=max(dp[j-2]+z[j],dp[j-1]); mx=max(mx,dp[j]); } sum[i]=mx; } int mx=0; dp[0]=0; dp[
1]=sum[1]; mx=dp[1]; for(int j=2;j<=n;j++) { dp[j]=max(dp[j-2]+sum[j],dp[j-1]); mx=max(mx,dp[j]); } printf("%d\n",mx); } return 0; }
View Code

H

n 然後n個操作 操作有3種

0 a 插入 a

1 a 刪除 a 如果a存在的話 不存在輸出 No Elment!

2 a k 查詢比a大的 第k個 不存在輸出 Not Find!

0 1
只是線段樹的單點更新 不多說

那麽 查詢比a大第k個 我是 先查了a在第x個 然後只要在樹上查第 x+k 有沒有就可以了

技術分享
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<math.h>
#include<queue>

using namespace std;

#define MAXN 100010
#define inf  1000000007
#define ll long long

struct node
{
    int l,r,w;
}tree[MAXN<<2];

int ok;
void Build(int l,int r,int a)
{
    tree[a].l=l;
    tree[a].r=r;
    tree[a].w=0;
    if(l==r)
        return ;
    int mid=(l+r)>>1;
    Build(l,mid,a<<1);
    Build(mid+1,r,a<<1|1);
}
void Update(int l,int r,int a1,int a)
{
    if(l==r)
    {
        tree[a].w=tree[a].w+1;
        return ;
    }
    int mid=(l+r)>>1;
    if(a1<=mid)
        Update(l,mid,a1,a<<1);
    else
        Update(mid+1,r,a1,a<<1|1);
    tree[a].w=tree[a<<1].w+tree[a<<1|1].w;
}
void Delete(int l,int r,int a1,int a)
{
    if(l==r)
    {
        if(tree[a].w==0)
            ok=1;
        else
            tree[a].w=tree[a].w-1;
        return ;
    }
    int mid=(l+r)>>1;
    if(a1<=mid)
        Delete(l,mid,a1,a<<1);
    else
        Delete(mid+1,r,a1,a<<1|1);
    tree[a].w=tree[a<<1].w+tree[a<<1|1].w;
}
int Ques(int l,int r,int k,int a)
{
    if(l==r)
        return l;
    int mid=(l+r)>>1;
    if(k>tree[a<<1].w)
    {
        return Ques(mid+1,r,k-tree[a<<1].w,a<<1|1);
    }
    else
    {
        return Ques(l,mid,k,a<<1);
    }
}
int Ques1(int l,int r,int a1,int b1,int a)
{
    if(a1<=l&&r<=b1)
        return tree[a].w;
    int ans=0;
    int mid=(l+r)>>1;
    if(a1<=mid)
        ans=ans+Ques1(l,mid,a1,b1,a<<1);
    if(b1>mid)
        ans=ans+Ques1(mid+1,r,a1,b1,a<<1|1);
    return ans;
}
int main()
{
    int n;
    int r=100000;
    while(scanf("%d",&n)!=EOF)
    {
        Build(1,r,1);
        while(n--)
        {
            int type;
            scanf("%d",&type);
            if(type==0)
            {
                int a;
                scanf("%d",&a);
                Update(1,r,a,1);
            }
            else if(type==1)
            {
                int a;
                scanf("%d",&a);
                ok=0;
                Delete(1,r,a,1);
               // printf("%d\n",ok);
                if(ok==1)
                    printf("No Elment!\n");
            }
            else
            {
                int a,k;
                ok=0;
                scanf("%d%d",&a,&k);
                int c=Ques1(1,r,1,a,1);
                k=k+c;
                if(k>tree[1].w)
                {
                    printf("Not Find!\n");
                    continue;
                }
                int ans=Ques(1,r,k,1);
                printf("%d\n",ans);
            }
        }
    }
    return 0;
}
View Code

B

n然後 n個串

m然後m個串 問上面有多少個串包括下面這個串 輸出m個數字

n個串建字典樹 abab 那麽就是 abab bab ab b 但是不能重復計數 那麽 加上個標記就行了

技術分享
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<math.h>
#include<queue>
#include<stdlib.h>

using namespace std;

#define MAXN 100010
#define inf  1000000007
#define ll long long

char s[25];
struct node
{
    int cnt,id;
    struct node *next[27];
    void cl()
    {
        memset(next,0,sizeof(next));
        cnt=1;
    }
};
int ok;
void Insert(char *s,struct node *p,int cou)
{
    while(*s)
    {
        int a=*s-a;
        if(p->next[a]==0)
        {
            p->next[a]=(struct node *)malloc(sizeof(struct node));
            (p->next[a])->cl();
            (p->next[a])->id=cou;
        }
        p=p->next[a];
        if(p->id!=cou)
        {
            (p->cnt)++;
            p->id=cou;
        }
        s++;
    }
}

int Ques(char *s,struct node *p)
{
    int len=strlen(s);
    for(int i=0;i<len;i++)
    {
        int a=s[i]-a;
        if(p->next[a])
            p=p->next[a];
        else
            return 0;
    }
    return p->cnt;
}

int main()
{
    int n,m;
    scanf("%d",&n);
    struct node * root;
    root=(struct node *)malloc(sizeof(struct node));
    root->cl();
    int cou=1;
    for(int i=1;i<=n;i++)
    {
        scanf("%s",s);
        ok=0;
        int len=strlen(s);
        for(int j=0;j<len;j++)
        {
            Insert(s+j,root,cou);
            ok=1;
        }
        cou++;
    }
    scanf("%d",&m);
    for(int i=1;i<=m;i++)
    {
        int ans=0;
        scanf("%s",s);
        ans=Ques(s,root);
        printf("%d\n",ans);
    }
    return 0;
}
View Code

C

給你一個2進制字符串a 然後一個數b 要求在這個字符串上補0或者1 使得b能整除a 求長度最小 字典序最小 不可能輸出impossibl
顯然是可能的 至少可以在最後加上b 然後 最多就是2^20次方 直接跑的 然後求一下列舉的b的倍數是不是包含a就可以了 a=0註意下

技術分享
#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<iostream>
#include<math.h>
#include<queue>
#include<stdlib.h>

using namespace std;

#define MAXN 100010
#define inf  1000000007
#define ll long long

char z[35];
char s[35];

int main()
{
    while(scanf("%s",z)!=EOF)
    {
        int a;
        scanf("%d",&a);
        int b=0;
        int len=strlen(z);
        for(int i=0;i<len;i++)
            b=b*2+z[i]-0;
        if(b%a==0)
        {
            printf("%d\n",b);
            continue;
        }
        for(int i=1;;i++)
        {
            int c=a*i;
                int cnt=0;
                int d=c;
                while(d)
                {
                    s[cnt++]=d%2+0;
                    d=d/2;
                }
                for(int j=0;j<(cnt+1)/2;j++)
                    swap(s[j],s[cnt-j-1]);
                int c1,c2;
                s[cnt]=\0;
                for(c1=c2=0;c1<cnt&&c2<len;)
                {
                    if(s[c1]==z[c2])
                    {
                        c1++;
                        c2++;
                    }
                    else
                    {
                        c1++;
                    }
                }
                if(c2==len)
                {
                    printf("%s\n",s);
                    break;
                }

        }
    }
    return 0;
}
View Code

G題意至今未讀懂

多校 2009 4