西山居初赛三 总结

弱到一定程度了... 不过还好.又涨经 

值和姿势了.....

hdu 4551 生日猜猜猜

  月份和日期都比较小, (12,31) 果断暴力, 然后判定下当前月份和天数是否合法.

#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;

int day[2][13] = {
    {0,31,28,31,30,31,30,31,31,30,31,30,31 }
    ,{0,31,29,31,30,31,30,31,31,30,31,30,31 }
};
int gcd(int a,int b){
    return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b){
    return a*b/gcd(a,b);
}
bool key(int y){
    if( (y%400==0) || ((y%100!=0)&&(y%4==0)) ) return true;
    return false;
}

bool legal(int m, int d, int y){
    if( d <= day[ key(y) ][m] ) return true;
    return false;
}
int main(){
    int T;
    scanf("%d", &T);
    for(int Case = 1; Case <= T; Case++){        
    int x, y, z;
        scanf("%d%d%d", &x,&y,&z);
        int cnt = 0, aa,bb;    
        for(int a = 1; a <= 12; a++){
            for(int b = 1; b <= 31; b++){
                if( (gcd(a,b)==x) && (lcm(a,b)==y) ){
                    if( legal(a,b,z) ){
                        cnt++;        
                        aa = a, bb = b;    
                    }    
                }    
            } 
        }
        printf("Case #%d: ", Case);
        if( cnt == 0 ) printf("-1\n");
        else if( cnt == 1 ) printf("%d/%02d/%02d\n", z, aa, bb);
        else puts("1");
    }
    return 0;
}
View Code

hdu 4552 怪盗基德的挑战书

  根据next函数定义, next[i+1]-1 表示 以i位置结尾的后缀所能完全匹配到的最长前缀. 定义dp[i]表示以i位置结尾的的串其前缀(包含子前缀)出现总次数, 则有 dp[i] += dp[ next[i+1]-1 ]. 初始dp[i] = 1,代表 [1,i]作为前缀的串出现了一次.  举例更容易理解点貌似:
  index:  1, 2, 3, 4, 5, 6, 7, 8, 9,

  letter:   a, b, c, a, a, b, c, a, -

  next :    0, 1, 1, 1, 2, 2, 3, 4, 5

  首先看dp[4],则以[1,4]为前缀串出现的次数, 初始值是1, 因为S(1,4)本身可作为前缀出现. 再看当前串S(1,4) 的最大后缀和最大前缀的长度为, next[5]-1 = 2-1 = 1. 则意味着最大相同前缀为 "a",  换句话说, S(1,4) 除了包含了一个(1,4)的前缀, 还包含了一个 (1,1)的前缀. 所以  dp[4] + dp[1]  = 2.  再到 i = 8, 此时串 S(1,8), 其最长前后缀为 next[9]-1 = 4. 其最大相同前后缀为 "abca", 同样的, 其除了包含了一个(1,8)的前缀外, 还包含了一个(1,4)的前缀, "abca", 所以此时以 S[8] 结束的串其前缀出现次数除了初始1外还要加上 dp[4]. 由前面可知 dp[4] = 2, 所以 dp[8] = 1 + dp[4] = 3.  其他类似.  

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<string>
#include<algorithm>
using namespace std;

const int N = (int)1e5+10;

int nxt[N], dp[N];
char s[N];
int main(){
    while( scanf("%s", s) != EOF){
        int i = 0, j = 1; nxt[1] = 0;
        int ans = 0, len = strlen(s);
        while( j <= len ){
            if( i == 0 || s[i-1] == s[j-1] )
                nxt[++j] = ++i;
            else i = nxt[i];
        }
        ans = 0;    
        dp[0] = 0;
        for(int i = 1; i <= len; i++) dp[i] = 1;
        for(int i = 1; i <= len; i++){
            if( nxt[i+1] > 1 )
                dp[i] += dp[ nxt[i+1]-1 ];
            ans += dp[i]; ans %= 256;    
        }
        printf("%d\n", ans );    
    }
    return 0;
}
View Code

  HDU还有个一样的.hdu 3336

   

hdu 4553 约会安排

  果断又涨经验了.... 表示看了别人思路才学会的....越来越渣...

  其实挺容易想到用线段书实现区间覆盖, 有三种:  空覆盖(清空), 被DS覆盖, 被NS覆盖. 然后对于三类覆盖有不同查询. 还要求长度.并且满足要求中要最左边的起始下标的. 然后就有点麻烦了....

  我们将 空覆盖看作0, DS覆盖看作1, 女神覆盖看做2.  

  分析下.可以发现 对于NS的查询操作:  若 全 00000满足要求长度的有, 则覆盖全0, 否则看 0101混合是否有满足要求长度.  而对于DS只能看 全0的是否有满足长度要求的.  并且所有查询操作, 若有满足要求的需要返回 最左边的下标. 则我们可以这样来设计查询 操作. 然后再看 需要哪些辅助信息来 维护查询.

int query(int rt,int l,int r,int len,int c){
    if( mx[rt][c] < len ) return -1;
    // mx[rt][c] >= len 
    if( l == r ) return l;
    int m = (l+r)>>1;
    push_down(rt,l,r);
    if( mx[rt<<1][c] >= len ) return query(lch,len,c);
    else if( conr[rt<<1][c]+conl[rt<<1|1][c] >= len ) return m-conr[rt<<1][c]+1;
    else if( mx[rt<<1|1][c] >= len ) return query(rch,len,c);
    return -1;
}

  若 左子区间 满足要求,则在左边找下去, 否则看左右组合是否满足, 若满足, 则返回下标 M - ConR[ lchild ] + 1. 否则在右子区间查找. 

  总体是维护一个左连续和, 右连续和. 以及区间最大和.   感脚这题比较神奇的是

    1. 转换.  0 表示连续0的,  而1, 表示01混合的.  

    2. 查询.  设计成  [ x1, M] + [ M+1, x2 ]  这样的形似. 然后下标即为  M-x1+1,  不断细分下去. 不过要特殊处理下, 当查询len=1,而 l == r无法结束,此时l即为所需下标.

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
#define lch rt<<1,l,m
#define rch rt<<1|1,m+1,r
const int N = (int)1e6+10;
int col[N<<2], mx[N<<2][2], conl[N<<2][2],conr[N<<2][2];
void push_up(int rt, int l, int r){
    int lc = rt<<1, rc = rt<<1|1, m = (l+r)>>1;
    for(int i = 0; i < 2; i++){
        //left sum    
        if( conl[lc][i] == m-l+1 )  
            conl[rt][i] = conl[lc][i] + conl[rc][i];
        else conl[rt][i] = conl[lc][i];
        //right sum    
        if( conr[rc][i] == r-m )
            conr[rt][i] = conr[rc][i] + conr[lc][i];
        else conr[rt][i] = conr[rc][i];
        //max sum    
        mx[rt][i] = max( mx[lc][i], mx[rc][i] );
        mx[rt][i] = max( mx[rt][i], conr[lc][i]+conl[rc][i] );
    }
}
void push_down(int rt,int l,int r){
    if( l == r ) return;    
    if( col[rt] != -1 ){
        int lc = rt<<1, rc = rt<<1|1, m = (l+r)>>1;
        col[lc] = col[rc] = col[rt];    
        if( col[rt] == 0 ){
            for(int i = 0; i < 2; i++){
                mx[lc][i]=conl[lc][i]=conr[lc][i]= m-l+1;
                mx[rc][i]=conl[rc][i]=conr[rc][i]= r-m;
            }
        }
        else if( col[rt] == 1 ){
            for(int i = 0; i < 2; i++){    
                mx[lc][i]=conl[lc][i]=conr[lc][i]= (i==0)? 0: m-l+1;
                mx[rc][i]=conl[rc][i]=conr[rc][i]= (i==0)? 0: r-m;    
            }    
        }
        else{ // col[rt] == 2
            for(int i = 0; i < 2; i++){
                mx[lc][i]=conl[lc][i]=conr[lc][i]= 0;
                mx[rc][i]=conl[rc][i]=conr[rc][i]= 0;    
            }    
        }
        col[rt] = -1;
    }
}
void build(int rt,int l,int r){
    col[rt] = -1;
    for(int i = 0; i < 2; i++)
        mx[rt][i] = conl[rt][i] = conr[rt][i] = r-l+1;
    if( l == r ) return;
    int m = (l+r)>>1;
    build( lch ), build( rch );
}
void update(int rt,int l,int r,int a,int b,int c){
    if(a <= l && r <= b){
        col[rt] = c;    
        if(c == 0){
            for(int i = 0; i < 2; i++)
                mx[rt][i]=conl[rt][i]=conr[rt][i]=r-l+1;    
        }else if(c == 1){
            for(int i = 0; i < 2; i++)
                mx[rt][i]=conl[rt][i]=conr[rt][i]=(i==0)?0:r-l+1;
        }else{
            for(int i = 0; i < 2; i++)
                mx[rt][i]=conl[rt][i]=conr[rt][i]=0;
        }
        return;
    }
    push_down(rt,l,r);    
    int m = (l+r)>>1;
    if(a <= m) update(lch,a,b,c);
    if(m <  b) update(rch,a,b,c);
    push_up(rt,l,r);
}
int query(int rt,int l,int r,int len,int c){
    if( mx[rt][c] < len ) return -1;
    // mx[rt][c] >= len 
    if( l == r ) return l;
    int m = (l+r)>>1;
    push_down(rt,l,r);
    if( mx[rt<<1][c] >= len ) return query(lch,len,c);
    else if( conr[rt<<1][c]+conl[rt<<1|1][c] >= len ) return m-conr[rt<<1][c]+1;
    else if( mx[rt<<1|1][c] >= len ) return query(rch,len,c);
    return -1;
}
int main(){
    freopen("1.in","r",stdin);    
    int _;
    scanf("%d", &_);
    for(int Case = 1; Case <= _; Case++){    
        printf("Case %d:\n", Case);    
        int n, m;
        scanf("%d%d", &n, &m);
        build( 1, 1, n );
        char op[10]; 
        int a, b, len;
        for(int i = 0; i < m; i++){
            scanf("%s",op);
            if( op[0] == 'D' ){
                scanf("%d", &len);
                int t = query(1,1,n,len,0);
                if( t == -1 ) puts("fly with yourself");
                else{
                    update(1,1,n, t,t+len-1,1);
                    printf("%d,let's fly\n", t);
                }
            }
            else if( op[0] == 'N'){
                scanf("%d", &len);
                int t = query(1,1,n,len,0);
                if( t == -1 ){
                    t = query(1,1,n,len,1);
                    if( t == -1 ) puts("wait for me");
                    else{
                        update(1,1,n, t,t+len-1,2);
                        printf("%d,don't put my gezi\n",t);
                    }
                }
                else{
                    update(1,1,n, t,t+len-1,2);
                    printf("%d,don't put my gezi\n",t);
                }
            }
            else{
                scanf("%d%d",&a,&b);
                puts("I am the hope of chinese chengxuyuan!!");
                update(1,1,n, a,b,0 );    
            }
        }
    }
    return 0;
}
View Code

   

原文地址:https://www.cnblogs.com/yefeng1627/p/3086827.html