JNday5-pm

 

GG

T1
貌似没有读懂题目,然而这是个简单的模拟

T2
首先 & 和 | 都是单调的,
& 和 | 可以用ST表来维护,枚举左端点,计算右端的的数量
利用ST表进行二分,跳过连续段

T3
又是一个GG的dp
背包?f[i][j] 表示i 号节点在子树中拿j 个果子的方案数。
O(n3)?
DFS 时可以直接把父节点状态传下去,减少一维合并复杂度。
O(n2)

T1 轮换

#include <cstdio>
#include <algorithm>

using namespace std;
int n,m,k;

int a[1005],b[1005],p[1005][1005];
int main(){
    freopen("rotate.in","r",stdin);
    freopen("rotate.out","w",stdout);
    scanf("%d%d%d",&n,&m,&k);
    for(int i=1;i<=n;i++) a[i]=i;
    for(int i=1,t;i<=m;i++){
        scanf("%d",&t);
        for(int j=1;j<=t;j++){
            scanf("%d",&b[j]);
        }
        for(int j=1;j<=n;j++) p[i][j] = j;
        for(int j=1;j<t;j++) p[i][b[j]] = b[j+1];
        p[i][b[t]] = b[1];
    }
    for(int i=1;i<=n;i++){
        int x = i;
        for(int j=m;j>=1;j--){
            x=p[j][x];
        }
        printf("%d ",x);
    }


    return 0;
}

T2 区间

#include <cstdio>
#include <cstring>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cassert>

using namespace std;
typedef long long LL;
LL mod = 1e9+7;
LL cnt;
int s[100005],n,a,b,c,d;
int sta[100005][20],sto[100005][20];
int aska(int l,int r){
    int L=r-l+1;
    int t = log2(L);
    return sta[l][t] & sta[r-(1<<t)+1][t];
}
int asko(int l,int r){
    int L=r-l+1;
    int t = log2(L);
    return sto[l][t] | sto[r-(1<<t)+1][t];
}
int main(){
    freopen("range.in","r",stdin);
    freopen("range.out","w",stdout);
    scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
    for(int i=1;i<=n;i++) scanf("%d",&s[i]),sta[i][0]=sto[i][0]=s[i];
    // puts("aaa");
        for(int j=1;j<20;j++)
            for(int i=1;i<=n;i++){
            if(i+(1<<j) -1 <=n){
                sta[i][j] = sta[i][j-1] & sta[i+(1<<(j-1))][j-1];
                sto[i][j] = sto[i][j-1] | sto[i+(1<<(j-1))][j-1];
            }
        }
    for(int i=1;i<=n;i++){
        int andsum = s[i], orsum = s[i];


        for(int j=i;j<=n;j++){
            int L=j,R=n+1;
            andsum = aska(i,j);
            orsum = asko(i,j);
            while(R-L>1){
                int mid = (L+R)/2;
                if(aska(i,mid) == andsum && asko(i,mid) == orsum){
                    L=mid;
                }else R=mid;
            }
            if(a <= andsum && andsum <= b && c <= orsum && orsum <= d){
                cnt += L-j+1;
            }
            j=L;
        }

    }
    cout<<cnt%mod<<endl;
    return 0;
}

T3 收集果子

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long LL;
LL mod = 1e9+7;
int n,k;
int a[1005];
int H[1005],X[2005],P[2005],tot;
inline void add(int x,int y){
    P[++tot]=y;X[tot]=H[x];H[x]=tot;
}
LL pw2[1005];
LL dp[1005][1005];

int dfs(int x,int fa){
    int siz=1;
    for(int i=H[x];i;i=X[i]){
        if(fa == P[i]) continue;
        for(int j=0;j<=n-a[P[i]];j++){
            dp[P[i]][j+a[P[i]]] = dp[x][j];
        }
        int tmp = dfs(P[i],x);
        for(int j=0;j<=n;j++){
            dp[x][j] = (pw2[tmp-1] * dp[x][j] % mod + dp[P[i]][j])% mod;
        }
        siz+=tmp;
    }
    return siz;
}
int main(){
    freopen("fruit.in","r",stdin);
    freopen("fruit.out","w",stdout);
    scanf("%d%d",&n,&k);

    pw2[0]= 1;
    for(int i=1;i<=n;i++) pw2[i] = pw2[i-1] * 2 % mod;
    for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
    }
    for(int i=1,x,y;i<n;i++){
        scanf("%d%d",&x,&y);
        add(x,y);add(y,x);
    }
    dp[1][a[1]] = 1;
    dfs(1,0);
    
    printf("%d\n",(int)dp[1][k]);
    return 0;
}

 

posted @ 2017-11-01 21:52  ioioioioioio  阅读(152)  评论(0编辑  收藏  举报