zoukankan      html  css  js  c++  java
  • 清北考前刷题da5下午好

    /*
    (4,1)*(3,1)*(2,1)的话1变成2然后一直是2
    2变成1然后变成3
    3变成1然后变成4
    4变成1
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    #define N 1007
    
    using namespace std;
    int n,m,p,k,ans,cnt,tmp;
    int a[N],pos[N];
    struct node{
        int len,q[N];
    }s[N];
    
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int main()
    {
        freopen("rotate.in","r",stdin);
        freopen("rotate.out","w",stdout);
        n=read();p=read();k=read();
        for(int i=1;i<=n;i++) a[i]=i,pos[i]=i;
        for(int i=p;i>=1;i--) 
        {
            s[i].len=read();
            for(int j=1;j<=s[i].len;j++) s[i].q[j]=read();
        }
        for(int i=1;i<=p;i++)
        {
            for(int j=2;j<=s[i].len;j++)
            {
                int x=s[i].q[j],y=s[i].q[1];
                swap(a[pos[x]],a[pos[y]]);
                swap(pos[x],pos[y]);
            }
        }
        for(int i=1;i<=n;i++) printf("%d ",a[i]);
        return 0;
    }

    /*
    60线段树
    */
    #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define mod 1000000007 #define N 1003 #define ll long long using namespace std; int n,a,b,c,d,ans,cnt; int And[N][N],Or[N][N]; int s[N]; struct tree{ int l,r,sum1,sum2; }tr[N<<2]; bool cmp(int a,int b){return a>b;} inline int read() { int x=0,f=1;char c=getchar(); while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();} return x*f; } inline void pushup(int k) { tr[k].sum1=tr[k<<1].sum1 & tr[k<<1|1].sum1; tr[k].sum2=tr[k<<1].sum2 | tr[k<<1|1].sum2; } void build(int k,int l,int r) { tr[k].l=l;tr[k].r=r; if(l==r) { tr[k].sum1=read(); tr[k].sum2=tr[k].sum1; return; } int mid=l+r>>1; build(k<<1,l,mid);build(k<<1|1,mid+1,r); pushup(k); } int query1(int k,int l,int r) { if(tr[k].l==l && tr[k].r==r) return tr[k].sum1; int mid=tr[k].l+tr[k].r>>1; pushup(k); if(r<=mid) return query1(k<<1,l,r); else if(l>mid) return query1(k<<1|1,l,r); else return query1(k<<1,l,mid) & query1(k<<1|1,mid+1,r); } int query2(int k,int l,int r) { if(tr[k].l==l && tr[k].r==r) return tr[k].sum2; int mid=tr[k].l+tr[k].r>>1; pushup(k); if(r<=mid) return query2(k<<1,l,r); else if(l>mid) return query2(k<<1|1,l,r); else return query2(k<<1,l,mid) | query2(k<<1|1,mid+1,r); } int main() { freopen("range.in","r",stdin); freopen("range.out","w",stdout); n=read();a=read();b=read();c=read();d=read(); build(1,1,n); for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) And[i][j]=query1(1,i,j),Or[i][j]=query2(1,i,j); for(int i=1;i<=n;i++) for(int j=i;j<=n;j++) if(And[i][j]<=b && And[i][j]>=a && Or[i][j]<=d && Or[i][j]>=c) { ans++; if(ans>mod) ans-=mod; } printf("%d ",ans); return 0; }
    /*
    有单调性
    枚举左端点,二分右端点,ST表处理,计算答案。
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include <cmath>
    
    #define N 100007
    #define ll long long
    #define mod 1000000007
    
    using namespace std;
    int n,a,b,c,d,ans;
    int st1[N][22],st2[N][22];
    int s[N];ll cnt;
    
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int query1(int l,int r)
    {
        int len=r-l+1,p=log2(len);
        return st1[l][p] & st1[r-(1<<p)+1][p];
    }
    
    int query2(int l,int r)
    {
        int len=r-l+1,p=log2(len);
        return st2[l][p] | st2[r-(1<<p)+1][p];
    }
    
    int main()
    {
        freopen("range.in","r",stdin);
        freopen("range.out","w",stdout);
        n=read();a=read();b=read();c=read();d=read();
        for(int i=1;i<=n;i++) 
          s[i]=read(),st1[i][0]=st2[i][0]=s[i];
        
        for(int j=1;j<=20;j++)  
          for(int i=1;i+(1<<j)-1<=n;i++)
            st1[i][j]=st1[i][j-1] & st1[i+(1<<(j-1))][j-1],
            st2[i][j]=st2[i][j-1] | st2[i+(1<<(j-1))][j-1];
        
        int sum1,sum2,L,R,mid;ans=0,cnt=0;
        for(int i=1;i<=n;i++)
        {
            sum1=sum2=s[i];
            for(int j=i;j<=n;j++)
            {
                sum1=query1(i,j);sum2=query2(i,j);
                L=j,R=n+1;
                while(L<=R)
                {
                    mid=L+R>>1;
                    if(query1(i,mid)==sum1 && query2(i,mid)==sum2) ans=mid,L=mid+1;
                    else R=mid-1;
                }
                if(a<=sum1 && sum1<=b && c<=sum2 && sum2<=d) cnt+=ans-j+1;j=ans;
            }
        }
        printf("%I64d
    ",cnt%mod);
        return 0;
    }

    /*
    不先考虑k个,1~n先都考虑。
    按子树为单位树形dp
    f[x][j]表示以x为根的子树有j个果子方案数。
    x显然果子必须拿,其他的果子需要分配。
    但如果有很多孩子,那么挨个分配会T。
    所以考虑树形dp常用策略把子树编号。
    考虑孩子的每个前缀分多少,还剩多少。
    就是每个前缀的max而不是子集的max。
    所以要设计前缀的状态:g[i][j]表示以i为结尾的前缀分j个果子的方案数。
    就转化为了背包问题。
    但直接转移是n^3的,考虑优化。
    可以看出枚举每个前缀是不必要的。
    从根节点递归到子节点往上反的时候子节点的状态先继承父节点的状态,然后进行转移。
    这样每个点都会从左到右把它儿子的每个前缀计算答案并取max。详见代码。
    */
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    
    #define mod 1000000007
    #define N 1007
    #define ll long long
    
    using namespace std;
    int n,m,ans,cnt;
    ll f[N][N],p[N];
    int val[N],head[N];
    struct edge{
        int u,v,net;
    }e[N<<1];
    
    inline int read()
    {
        int x=0,f=1;char c=getchar();
        while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    inline void add(int u,int v)
    {
        e[++cnt].v=v;e[cnt].net=head[u];head[u]=cnt;
    }
    
    int dp(int u,int fa)
    {
        int siz=1;
        for(int i=head[u];i;i=e[i].net)
        {
            int v=e[i].v;
            if(v==fa) continue;
            for(int j=0;j<=n-val[v];j++) f[v][j+val[v]]=f[u][j];
            int tmp=dp(v,u);
            for(int j=0;j<=n;j++)
              f[u][j]=(p[tmp-1]*f[u][j]%mod+f[v][j])%mod;
            siz+=tmp;
        }return siz;
    }
    
    int main()
    {
        int x,y,z;
        n=read();m=read();p[0]=1;
        for(int i=1;i<=n;i++)p[i]=(p[i-1]*2)%mod;
        for(int i=1;i<=n;i++) val[i]=read();
        for(int i=1;i<n;i++)
        {
            x=read();y=read();
            add(x,y);add(y,x);
        }
        f[1][val[1]]=1;dp(1,0);
        printf("%d
    ",int(f[1][m]));
        return 0; 
    }
    折花枝,恨花枝,准拟花开人共卮,开时人去时。 怕相思,已相思,轮到相思没处辞,眉间露一丝。
  • 相关阅读:
    类的加载次序与继承
    十进制转二进制算法
    面象对象与面象过程内存分区
    C/C++单向链表
    字符串与数字互相转换算法
    C#模拟进度条
    数据类型与类型转
    win7删除一些顽固的文件夹
    快速卸载VS2015的办法
    Js获取图片原始宽高
  • 原文地址:https://www.cnblogs.com/L-Memory/p/7768678.html
Copyright © 2011-2022 走看看