FOJ月賽 2015年3月(留坑)

A.簡單題(kmp)鏈接

解法:把每個壓縮的字符展開,然後kmp即可

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std ;

const int N = 1e6 + 11 ;
const int M = 1e3 + 11 ;

char str1[N] , str2[M] ;
int len1 , len2 ;
char ss[M] ;
int jump[M] ;

void getjump() {
    int i = 0 , j = -1 ;
    jump[0] = -1 ;
    while(i < len2) {
        if(j == -1 || str2[i] == str2[j]) {
            ++i , ++j ;
            jump[i] = j ;
        }else j = jump[j] ;
    }
}


bool check() {
    getjump() ;
    int i = 0 , j = 0 ;
    while(i < len1) {
        if(j == -1 || str1[i] == str2[j]) {
            ++i , ++j ;
            if(j >= len2) return true ;
        }else j = jump[j] ;
    }
    return false ;
}

int main() {
    //freopen("data.in" , "r" , stdin) ;
    while(scanf("%s %s" , ss , str2)==2) {
        int cnt = 0 ;
        len1 = strlen(ss) ;
        len2 = strlen(str2) ;
        for(int i = 0 ; i < len1 ; ++i) {
            if(ss[i] >= 'a' && ss[i] <= 'z') {
                str1[cnt++] = ss[i] ;
            }else {
                int ret = 0 ;
                int id  = i+1 ;
                while(ss[id] != ']') {
                    ret *= 10 ;
                    ret += ss[id] - '0' ;
                    id++ ;
                }
                char tmp = ss[i-1] ;
                i = id ;
                if(ret  > len2) ret = len2 ;
                while(ret--) {
                    str1[cnt++] = tmp ;
                }
            }
        }
        len1 = cnt ;
        if(check()) printf("True\n") ;
        else printf("False\n") ;
    }
}

B.逆序數還原(樹狀數組+二分)鏈接

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std ;

const int N = 1e3 + 11 ;

int arr[N] ;
int n ;

int lowbit(int x) {
    return (x&-x) ;
}

void update(int x ,int d) {
    for(int i = x ; i <= n ; i += lowbit(i)) {
        arr[i] += d ;
    }
}

int query(int x) {
    int ans = 0 ;
    for(int i = x ; i > 0 ; i -= lowbit(i)) {
        ans += arr[i] ;
    }
    return ans ;
}

void init() {
    memset(arr , 0 , sizeof(arr)) ;
    for(int i = 1 ; i <= n ;++i) {
        update(i , 1) ;
    }
}

int fun(int x) {
    int l = 1 , r = n ;
    int mid , f ;
    while(l < r) {
        mid = (l+r)>>1 ;
        f = query(mid) ;
        if(f >= x) r = mid ;
        else l = mid+1 ;
    }
    update(r , -1) ;
    return r ;
}

int main() {//freopen("data.in" , "r" , stdin) ;
    while(scanf("%d" ,&n)==1) {
        init() ;
        int a ;
        for(int i = 1 ; i <= n ; ++i) {
            scanf("%d" ,&a) ;
            printf("%d" , fun(a+1));
            if(i == n) printf("\n") ;
            else printf(" ") ;
        }
    }
}

C.樹的路徑覆蓋鏈接

D.小明的迷宮鏈接

E.回家種地(掃描線)鏈接

求覆蓋大於一次的面積

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std ;

const int N = 2e5 + 11 ;
typedef long long LL ;

struct Line {
    int x1 , x2 , h , d ;
    Line(){}
    Line(int a ,int b , int c , int dd) {
        x1 = a , x2 = b , h = c , d = dd ;
    }

    friend bool operator<(const Line& a , const Line& b) {
        return a.h < b.h  ;
    }
};

int n ;
Line line[N] ; int nline ;
int num[N] ; int nn ;

struct Segment {
    int w0[N<<2] , w1[N<<2] ;
    int len[N<<2] ;
    int cover[N<<2] ;
    int x1 , y1 ;
    int n ;

    void init(int x) {
        n = x ;
        build(1 , 1 , n) ;
    }

    void up(int u) {
        int lson = u<<1 , rson = u<<1|1 ;
        if(cover[u] > 1) {
            w0[u] = w1[u] = len[u] ;
        }else if(cover[u] == 1) {
            w1[u] = w0[lson] + w0[rson] ;
            w0[u] = len[u] ;
        }else {
            w1[u] = w1[lson] + w1[rson] ;
            w0[u] = w0[lson] + w0[rson] ;
        }
    }

    void build(int u , int l , int r) {
        cover[u] = 0 ;
        if(l+1 == r) {
            len[u] = num[r-1]-num[l-1] ;
            w0[0] = w1[0] = 0 ;
            return ;
        }
        int mid = (l+r)>>1 ;
        build(u<<1 , l , mid) ;
        build(u<<1|1 , mid , r) ;
        len[u] =len[u<<1] + len[u<<1|1] ;
        up(u) ;
    }

    void update(int l , int r , int d) {
        x1 = l , y1 = r ;
        _update(1 , 1 , n , d) ;
    }

    void _update(int u , int l , int r , int d) {
        if(x1 <= l && r <= y1) {
            cover[u] += d ;
            if(l+1 == r) {
                if(cover[u] > 1) {
                    w1[u] = w0[u] = len[u] ;
                }else if(cover[u] == 1) {
                    w1[u] = 0 ;
                    w0[u] = len[u] ;
                }else {
                    w1[u] = w0[u] = 0 ;
                }
            }else {
                up(u) ;
            }
            return ;
        }
        int mid = (l+r)>>1 ;
        if(x1 < mid) _update(u<<1 , l , mid , d) ;
        if(y1 > mid) _update(u<<1|1 , mid , r , d) ;
        up(u) ;
    }
}seg;

void init() {
    int x1 , y1 , x2 , y2 ;
    nline = nn = 0 ;
    for(int i = 1 ; i <= n ; ++i) {
        scanf("%d %d %d %d" , &x1 , &y1 , &x2 , &y2) ;
        line[nline++] = Line(x1 , x2 , y1 , 1) ;
        line[nline++] = Line(x1 , x2 , y2 , -1) ;
        num[nn++] = x1 , num[nn++] = x2 ;
    }
    sort(line , line+nline) ;
    sort(num , num+nn) ;
    nn = unique(num , num+nn)-num ;
}

int at(int x) {
    return lower_bound(num , num+nn , x)-num+1 ;
}

void work() {
    seg.init(nn) ;
    int last = line[0].h ;
    LL area = 0 ;
    for(int i = 0 ; i < nline ; ++i) {
        area += (LL)(seg.w0[1] - seg.w1[1])*(line[i].h-last) ;
        last = line[i].h ;
        seg.update(at(line[i].x1) , at(line[i].x2) , line[i].d) ;
    }
    printf("%I64d\n" , area) ;
}

int main() {
    //freopen("data.in" , "r" ,stdin) ;
    int t , tt = 0;
    scanf("%d" ,&t) ;
    while(t--) {
        printf("Case %d: " , ++tt);
        scanf("%d" ,&n) ;
        init() ;
        work() ;
    }
}

F.過河I(bfs)鏈接

解法:bfs ,注意當羊爲0的時候,狼可以大於羊;每次必須運送大於1只動物

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cassert>
using namespace std ;

bool vis[201][201][2] ;

struct Node {
    int wolf , sheep ;
    int t ;
    bool side ;
};

int x , y , n ;

void work() {
    if(y > x && x != 0) {printf("-1\n") ; return ;}
    memset(vis , 0 , sizeof(vis)) ;
    Node fro ;
    fro.wolf = y , fro.sheep = x , fro.side = false;
    fro.t = 0 ;
    vis[x][y][0] = true ;
    queue<Node> que ;
    que.push(fro) ;
    while(!que.empty()) {
        //cout<<fro.sheep<<" "<<fro.wolf<<" "<<fro.side<<endl;
        fro = que.front() ;
        que.pop() ;
        if(fro.sheep == 0 && fro.wolf == 0 && fro.side == false || fro.sheep == x && fro.wolf == y && fro.side == true) {
            printf("%d\n" , fro.t) ;
            return ;
        }
        ++fro.t ;
        int wolf = fro.wolf , sheep = fro.sheep ;
        int other_wolf = y - wolf , other_sheep = x - sheep ;
        for(int i = 1 ; i <= sheep ; ++i) {
            for(int j = 0 ; j <= wolf && j <= i&& (i+j)<= n ; ++j) {
                if(sheep-i != 0 && sheep-i < wolf-j) continue ;
                if(other_sheep+i < other_wolf+j) continue ;
                Node tmp ; tmp.t = fro.t ;
                tmp.sheep = other_sheep+i , tmp.wolf = other_wolf+j , tmp.side = !fro.side ;
                if(vis[tmp.sheep][tmp.wolf][tmp.side]) continue ;
                vis[tmp.sheep][tmp.wolf][tmp.side] = true ;
                que.push(tmp) ;
            }
        }
        for(int j = 1 ; j <= wolf && j <= n ; ++j) {
            if(sheep != 0 && sheep < wolf-j) continue ;
            if(other_sheep != 0 && other_sheep < other_wolf+j) continue ;
            Node tmp ; tmp.t = fro.t ;
            tmp.sheep = other_sheep , tmp.wolf = other_wolf+j , tmp.side = !fro.side ;
            if(vis[tmp.sheep][tmp.wolf][tmp.side]) continue ;
            vis[tmp.sheep][tmp.wolf][tmp.side] = true ;
            que.push(tmp) ;
        }
    }
    printf("-1\n") ;
}

int main() {
   // freopen("data.in" ,"r" , stdin) ;
    while(scanf("%d %d %d" ,&x , &y , &n)==3) {
        work() ;
    }
}

G.過河II鏈接

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章