zoukankan      html  css  js  c++  java
  • Day5下

    T1

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    using namespace std;
    const int N=1010;
    int n,m,k,p;
    int to[N],nex[N];
    int a[N][N];
    int main()
    {
        freopen("rotate.in","r",stdin);
        freopen("rotate.out","w",stdout);
        scanf("%d%d%d",&n,&p,&k);
        for(int j=1;j<=n;j++)    to[j]=j;
        for(int i=1;i<=p;i++)
        {
            scanf("%d",&m);a[i][0]=m;
            for(int j=1;j<=m;j++)    scanf("%d",&a[i][j]);
        }
        for(int i=p;i>=1;i--)
        {
            memset(nex,0,sizeof nex);m=a[i][0];
            
            for(int j=2;j<=m;j++)    nex[a[i][j-1]]=a[i][j];
            nex[a[i][m]]=a[i][1];
            
            for(int j=1;j<=n;j++)
            if(nex[to[j]])    to[j]=nex[to[j]];
        }
        for(int j=1;j<=n;j++)
        printf("%d ",to[j]);
        return 0;
    }
    first 100

    置换,没学过的话模拟就行。考察理解题意了。

    正着做:置换的性质。(不知道也能做)

    T2

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    using namespace std;
    const int N=1e4+100;
    int n,a,b,c,d;
    int q[N];
    long long ans;
    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",&q[i]);
        
        for(int i=1,j;i<=n;i++)
        {
            int ans1,ans2;
            ans1=ans2=q[i];
            if(ans1<a||ans2>d)    continue;
            j=i;
            for(j;j<=n;j++)
            {
                ans1&=q[j];ans2|=q[j];
                if(ans1<a||ans2>d)    break;
                if(ans1<=b&&ans2>=c)    ans++;
            }
        }
        cout<<ans<<endl;
        return 0;
    } 
    first 60 
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #include<cmath>
    #include<ctime>
    using namespace std;
    typedef long long  LL;
    const int N=1e5+7;
    const LL P=1e9+7;
    LL ans;
    int s[N],sta[N][21],sto[N][21];
    int worka(int l,int r)
    {
        int L=r-l+1;
        int t=log2(L);
        return sta[l][t]&sta[r-(1<<t)+1][t];
    }
    int worko(int l,int r)
    {
        int L=r-l+1;
        int t=log2(L);
        return sto[l][t]|sto[r-(1<<t)+1][t];
    }
    int n,a,b,c,d;
    int main()
    {
        freopen("range.in","r",stdin);
        freopen("range-me.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];
        }
        
        //预处理倍增,下一步能O(1)查询区间值 
        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)][j-1];
            sto[i][j]=sto[i][j-1]|sto[i+(1<<j)][j-1];
        }
        //查找区间(具有单调性)
        for(int i=1;i<=n;i++)
        {
            int andans,orans;
        //    andans=orans=s[i];
            int j=i;
            while(j<=n)
            {
                int L=j,R=n+1,mid;
                andans=worka(i,j);
                orans=worko(i,j);
                while(R-L>1)
                {
                    mid=(L+R)>>1;
                    if(worka(i,mid)==andans&&worko(i,mid)==orans)
                        L=mid;
                    else R=mid;
                }
                if(andans>=a&&andans<=b&& orans>=c&&orans<=d)
                ans+=L-j+1;
                j=L;
            } 
            
        } 
        cout<<ans%P;
    }
    二分+st优化 

    先固定左端典,向右搜,查找区间个数。

    怎么优化,二分 +倍增。

    本来我想’与‘和’或‘是不满足 前缀差等于区间值的性质的

    其实我的想法太狭隘了,仔细想想:无论是’与‘还是’或‘ 都满足两段区间O(1)合成更大区间的性质。

    比如f[1,6] & f[3,9],  可以看成f[1,3] & f[3,6]&f[6,9] &f[3,6] 一个数和本身的’‘与’还是本身无影响。

    然后就能通过二分把n^n变成nlogn,

    T3

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    using namespace std;
    const int N=1009;
    const int P=1e9+7;
    int n,k;
    int h[N],nex[N*2],to[N*2],cnt;
    int w[N],sum[N],tot[N];//子树节点数,根到这的和 
    int x,y;
    void add()
    {
        scanf("%d%d",&x,&y);
        to[++cnt]=y,nex[cnt]=h[x],h[x]=cnt;
        to[++cnt]=x,nex[cnt]=h[y],h[y]=cnt;
    }
    int vis[N];int ans;
    void dfs(int Tot,int Sum,int last)
    {
        if(Tot==k)
        {
            int ss=Sum;
            for(int i=1;i<=n;i++)
            if(vis[i])
            for(int j=h[i];j;j=nex[j])
            if(!vis[to[j]])        Sum++;
            Sum=n-1-Sum;
            ans=(1LL*ans+1LL*(1<<Sum)%P)%P;         
            
        
            Sum=ss;    
        }
        if(Tot>k)    return ;
        for(int i=last;i<=n;i++)
        if(vis[i])
        {
            int is=0;
            for(int j=h[i];j;j=nex[j])
            if(!vis[to[j]])    {
                vis[to[j]]=1;
                dfs(Tot+w[to[j]],Sum+1,i);
                vis[to[j]]=0;
            is=1;        
            }        
        }
    }
    int main()
    {
        freopen("fruit.in","r",stdin);
        freopen("fruit.out","w",stdout);
        scanf("%d%d",&n,&k);
        int is=1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&w[i]);
            if(!w[i])    is=0;
        }
        for(int i=1;i<n;i++)    add();
            
        vis[1]=1;
        dfs(w[1],0,1);
        if(!is) ans--;
        cout<<ans;
        return 0;
    }
    0分 
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long long LL;
    const LL P= 1e9+7;
    const int N=1009;
    int n,k;
    int a[N];
    int h[N],nex[N*2],to[N*2],cnt;
    LL f[N][N];
    int x,y;
    void add()
    {
        scanf("%d%d",&x,&y);
        to[++cnt]=y,nex[cnt]=h[x],h[x]=cnt;
        to[++cnt]=x,nex[cnt]=h[y],h[y]=cnt;
    }
    int dfs(int x,int fa)
    {
        int sum=1,tmp;
        for(int i=h[x];i;i=nex[i])
        {
            if(to[i]==fa)    continue;
            for(int j=0;j<=n-a[to[i]];j++)
                f[to[i]][j+a[to[i]]]=f[x][j];
            tmp=dfs(to[i],x);
            for(int j=0;j<=n;j++)
            f[x][j]=(f[x][j]*(1<<(tmp-1))+f[to[i]][j])%P;
            sum+=tmp;
        }
        return sum;
    }
    int main()
    {
        freopen("d.in","r",stdin);
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        for(int i=1;i<n;i++)    add();
        
        f[1][a[1]]=1;
        dfs(1,0);
        printf("%lld",(f[1][k]));
    }
    树上dp

    说到T3我就不得不吐槽一下,我投入了整套题考试总时间中超过一半的时间,结果0分。遗憾啊。

    搜索 搜重了,不知道怎么去重。

    正解是个背包(我没看出来。。。),f[i][j]表示在i节点及其子树中拿j个果子的方案数,。

    转移的话先遍历子节点,再根据已有信息更新其他字节点,和其父节点。

      dp[x][j] = ((1<<(tmp-1) * dp[x][j] % mod + dp[son][j])% mod

    (除了直接相连的边必须断掉之外,其他边怎样都行,2^n 种状态。

  • 相关阅读:
    游标cursor
    SQL: EXISTS
    LeetCode Reverse Integer
    LeetCode Same Tree
    LeetCode Maximum Depth of Binary Tree
    LeetCode 3Sum Closest
    LeetCode Linked List Cycle
    LeetCode Best Time to Buy and Sell Stock II
    LeetCode Balanced Binary Tree
    LeetCode Validate Binary Search Tree
  • 原文地址:https://www.cnblogs.com/CLGYPYJ/p/7767961.html
Copyright © 2011-2022 走看看