• 11.5 两次考试


    上午

    题还是比较水的...

    T1 attack

    题意:

    给一个有向图,Q次询问K个点,问从1到K个点的必经点 (没说是DAG,但数据是DAG...)、

    支配树的裸题吗,但是不会支配树啊....

    然后就求割点,桥,然后就懵逼了....

    DAG上支配树直接增量构造就好了

    有环的还不会...

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    inline void read(int &x)
    {
        x=0; int ff=1; char q=getchar();
        while(q<'0'||q>'9') { if(q=='-') ff=-1; q=getchar(); }
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
        x*=ff;
    }
    const int N=100006;
    int first[N],ver[N<<1],nt[N<<1],e;
    void addb(int u,int v)
    {
        ver[e]=v;
        nt[e]=first[u];
        first[u]=e++;
    }
    struct FAN
    {
        int first[N],ver[N<<1],nt[N<<1],e;
        void clear()
        {
            e=0; mem(first,-1);
        }
        void addb(int u,int v)
        {
            ver[e]=v;
            nt[e]=first[u];
            first[u]=e++;
        }
    }h[2];
    
    int n,m,Q,K;
    int maxk;
    int deg[N];
    
    int fa[N],dep[N],st[N][21];
    int LCA(int x,int y)
    {
        if(dep[x]<dep[y]) x^=y,y^=x,x^=y;
        int j;
        for(j=maxk;~j;--j)
            if(dep[x]-(1<<j)>=dep[y])
                x=st[x][j];
        if(x==y) return x;
        for(j=maxk;~j;--j)
            if(st[x][j]!=-1&&st[x][j]!=st[y][j])
                x=st[x][j],y=st[y][j];
        return fa[x];
    }
    void match(int x,int y)
    {
        fa[x]=y; dep[x]=dep[y]+1; st[x][0]=y;
        int j;
        for(j=1;j<=maxk&&st[x][j-1]!=-1;++j)
            st[x][j]=st[st[x][j-1]][j-1];
    }
    
    int dui[N<<2],he,en;
    void build()
    {
        while((1<<maxk)<=n) ++maxk; --maxk;
        mem(st,-1); fa[1]=-1;
        he=1; en=0;
        dui[++en]=1;
        int now,ve,las; rint i;
        while(en>=he)
        {
            now=dui[he++]; las=0;
            for(i=h[0].first[now];i!=-1;i=h[0].nt[i])
            {
                ve=h[0].ver[i];
                if(las)
                    las=LCA(las,ve);
                else
                    las=ve;
            }
            if(las)
                match(now,las);
            for(i=first[now];i!=-1;i=nt[i])
            {
                --deg[ver[i]];
                if(!deg[ver[i]])
                    dui[++en]=ver[i];
            }
        }
    }
    
    void work()
    {
        rint i,j; int tin,las;
        for(i=1;i<=Q;++i)
        {
            read(K); las=0;
            for(j=1;j<=K;++j)
            {
                read(tin);
                if(las)
                    las=LCA(las,tin);
                else
                    las=tin;
            }
            printf("%d
    ",dep[las]+1);
        }
    }
    
    int main(){
    
        rint i; int tin1,tin2;
        mem(first,-1); h[1].clear(); h[0].clear();
    
        read(n); read(m); read(Q);
        for(i=1;i<=m;++i)
        {
            read(tin1); read(tin2);
            ++deg[tin2];
            addb(tin1,tin2);
            h[0].addb(tin2,tin1);
        }
        build();
        work();
    }
    T1

    T2 reverse

    大水题,模拟就行了

    我用了双取模...

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    #define ull unsigned long long
    using namespace std;
    inline void read(int &x)
    {
        x=0; int ff=1; char q=getchar();
        while(q<'0'||q>'9') { if(q=='-') ff=-1; q=getchar(); }
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
        x*=ff;
    }
    const int P1=76543;
    const int P2=1000003;
    const int LEN=5006;
    
    int T;
    int lena,lenb;
    int la,ra,fa,lb,rb,fb;
    char A[LEN],B[LEN];
    ull prea1[LEN],sufa1[LEN],prea2[LEN],sufa2[LEN];
    ull preb1[LEN],sufb1[LEN],preb2[LEN],sufb2[LEN];
    ull PP1[LEN],PP2[LEN];
    
    void rota()
    {
        if(fa)
        {
            if(A[la]=='A')
                ++la;
            else
                ++la,fa^=1;
        }
        else
        {
            if(A[ra]=='A')
                --ra;
            else
                --ra,fa^=1;
        }
        --lena;
    }
    
    void rotb()
    {
        if(fb)
        {
            if(B[lb]=='A')
                ++lb;
            else
                ++lb,fb^=1;
        }
        else
        {
            if(B[rb]=='A')
                --rb;
            else
                --rb,fb^=1;
        }
        --lenb;
    }
    
    int check()
    {
        ull haa1,haa2,hab1,hab2;
        if(fa)
        {
            haa1=(sufa1[la]-sufa1[ra+1]*PP1[ra-la+1]);
            haa2=(sufa2[la]-sufa2[ra+1]*PP2[ra-la+1]);
        }
        else
        {
            haa1=(prea1[ra]-prea1[la-1]*PP1[ra-la+1]);
            haa2=(prea2[ra]-prea2[la-1]*PP2[ra-la+1]);
        }
        if(fb)
        {
            hab1=(sufb1[lb]-sufb1[rb+1]*PP1[rb-lb+1]);
            hab2=(sufb2[lb]-sufb2[rb+1]*PP2[rb-lb+1]);
        }
        else
        {
            hab1=(preb1[rb]-preb1[lb-1]*PP1[rb-lb+1]);
            hab2=(preb2[rb]-preb2[lb-1]*PP2[rb-lb+1]);
        }
        if(haa1==hab1&&haa2==hab2)
            return 1;
        return 0;
    }
    
    void prin()
    {
        rint i;
        if(fa)
        {
            for(i=ra;i>=la;--i)
                printf("%c",A[i]);
        }
        else
        {
            for(i=la;i<=ra;++i)
                printf("%c",A[i]);
        }
        
        printf("
    ");
        
        /*if(fb)
        {
            for(i=rb;i>=lb;--i)
                printf("%c",B[i]);
        }
        else
        {
            for(i=lb;i<=rb;++i)
                printf("%c",B[i]);
        }
        printf("
    ");*/
    }
    
    void work()
    {
        rint i; int len;
        fa=fb=0; la=lb=1; ra=lena; rb=lenb;
        for(i=lena;i;--i) A[i]=A[i-1]; A[0]=0;
        for(i=lenb;i;--i) B[i]=B[i-1]; B[0]=0;
        
        /*printf("
    ");
        for(i=1;i<=lena;++i)
            printf("%c",A[i]);
        printf("
    ");*/
        
        for(i=1;i<=lena;++i)
            prea1[i]=(prea1[i-1]+A[i])*P1,
            prea2[i]=(prea2[i-1]+A[i])*P2;
        for(i=1;i<=lenb;++i)
            preb1[i]=(preb1[i-1]+B[i])*P1,
            preb2[i]=(preb2[i-1]+B[i])*P2;
        for(i=lena;i;--i)
            sufa1[i]=(sufa1[i+1]+A[i])*P1,
            sufa2[i]=(sufa2[i+1]+A[i])*P2;
        for(i=lenb;i;--i)
            sufb1[i]=(sufb1[i+1]+B[i])*P1,
            sufb2[i]=(sufb2[i+1]+B[i])*P2;
        while(lena>lenb) rota();
        while(lenb>lena) rotb();
        
        //prin();
        
        len=lena;
        for(i=len;i;--i)
        {
            if(check())
            {
                prin();
                return ;
            }
            rota(); rotb();
        }
        puts("-1");
    }
    
    int main(){
        
        //freopen("T2.in","r",stdin);
        
        //freopen("reverse.in","r",stdin);
        //freopen("reverse.out","w",stdout);
        
        rint i;
        PP1[0]=PP2[0]=1;
        for(i=1;i<LEN;++i)
            PP1[i]=PP1[i-1]*P1,
            PP2[i]=PP2[i-1]*P2;
        
        read(T);
        while(T--)
        {
            mem(A,0); mem(B,0);
            mem(prea1,0); mem(prea2,0); mem(sufa1,0); mem(sufa2,0);
            mem(preb1,0); mem(preb2,0); mem(sufb1,0); mem(sufb2,0);
            scanf("%s%s",A,B);
            lena=strlen(A); lenb=strlen(B);
            work();
        }
    }
    T2

    T3 tree

    原题

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define dd double
    #define rint register int
    using namespace std;
    inline void read(int &x)
    {
        x=0; int ff=1; char q=getchar();
        while(q<'0'||q>'9') { if(q=='-') ff=-1; q=getchar(); }
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
        x*=ff;
    }
    const int N=100006;
    int first[N],nt[N<<1],ver[N<<1],e;
    void addb(int u,int v)
    {
        ver[e]=v;
        nt[e]=first[u];
        first[u]=e++;
    }
    
    int n,maxk;
    ll sumg[N],f[N],g[N];
    
    int fa[N];//dep[N];
    void dfs1(int x)
    {
        f[x]=1;
        int i;
        for(i=first[x];i!=-1;i=nt[i])
            if(ver[i]!=fa[x])
            {
                fa[ver[i]]=x;
                //dep[ver[i]]=dep[x]+1;
                dfs1(ver[i]);
                f[x]+=f[ver[i]]+1;
            }
    }
    void dfs2(int x)
    {
        if(fa[x]!=-1)
            sumg[x]=sumg[fa[x]];
        sumg[x]+=g[x];
        int i;
        for(i=first[x];i!=-1;i=nt[i])
            if(ver[i]!=fa[x])
            {
                if(fa[x]!=-1)
                    g[ver[i]]=g[x]+1;
                g[ver[i]]+=(1+f[x]-(f[ver[i]]+1)-1);
                dfs2(ver[i]);
            }
    }
    
    int main(){
        
        //freopen("T3.in","r",stdin);
        //freopen("T3.out","w",stdout);
        
        //freopen("tree.in","r",stdin);
        //freopen("tree.out","w",stdout);
        
        rint i; int tin1,tin2;
        mem(first,-1);
        
        read(n);
        for(i=1;i<n;++i)
        {
            read(tin1); read(tin2);
            addb(tin1,tin2);
            addb(tin2,tin1);
        }
        fa[1]=-1; dfs1(1);
        dfs2(1);
        
        for(i=1;i<=n;++i)
            printf("%lld.000
    ",sumg[i]+1);
    }
    T3

    下午

    T1 入阵曲

    $O(n^3)$枚举,打个时间戳

    ans忘开long long了...30分

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    //#include <ctime>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    inline void read(int &x)
    {
        x=0; int ff=1; char q=getchar();
        while(q<'0'||q>'9') { if(q=='-') ff=-1; q=getchar(); }
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
        x*=ff;
    }
    const int N=1000006;
    
    int n,m,mod;
    int sum[406][406];
    int tim[N],timer,cnt[N];
    ll ans;
    
    int main(){
        
        //freopen("T1.in","r",stdin);
        //freopen("T1.out","w",stdout);
        
        //freopen("rally.in","r",stdin);
        //freopen("rally.out","w",stdout);
        
        rint i,j,l,r; rint tt;
        
        read(n); read(m); read(mod);
        for(i=1;i<=n;++i)
            for(j=1;j<=m;++j)
            {
                read(tt);
                sum[i][j]=(sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+tt+mod)%mod;
            }
        for(l=1;l<=m;++l)
            for(r=l;r<=m;++r)
            {
                ++timer;
                tim[0]=timer; cnt[0]=1;
                for(i=1;i<=n;++i)
                {
                    tt=(sum[i][r]-sum[i][l-1]+mod)%mod;
                    if(tim[tt]==timer)
                        ans+=cnt[tt],++cnt[tt];
                    else
                        tim[tt]=timer,cnt[tt]=1;
                }
            }
        printf("%lld
    ",ans);
    //    printf("
    %d
    ",clock());
    }
    T1

    T2 将军令

    poi火药那个题的削弱版

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    inline void read(int &x)
    {
        x=0; int ff=1; char q=getchar();
        while(q<'0'||q>'9') { if(q=='-') ff=-1; q=getchar(); }
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
        x*=ff;
    }
    const int N=100006;
    int first[N],ver[N<<1],nt[N<<1],e;
    void addb(int u,int v)
    {
        ver[e]=v;
        nt[e]=first[u];
        first[u]=e++;
    }
    
    int n,K,op;
    int ans;
    
    int d[N],le[N],fa[N];
    void dfs(int x)
    {
        d[x]=0;
        int i;
        for(i=first[x];i!=-1;i=nt[i])
            if(ver[i]!=fa[x])
            {
                fa[ver[i]]=x;
                dfs(ver[i]);
                if(d[ver[i]]!=-1&&d[x]<d[ver[i]]+1)
                    d[x]=d[ver[i]]+1;
                if(le[ver[i]]!=-1&&le[x]<le[ver[i]]-1)
                    le[x]=le[ver[i]]-1;
            }
        if(le[x]>=d[x])
            d[x]=-1;
        if(d[x]==K)
        {
            d[x]=-1;
            ++ans;
            le[x]=K;
        }
    }
    
    int main(){
        
        //freopen("T2.in","r",stdin);
        //freopen("general.in","r",stdin);
        //freopen("general.out","w",stdout);
        
        rint i; int tin1,tin2;
        mem(first,-1);
        
        read(n); read(K); read(op);
        for(i=1;i<n;++i)
        {
            read(tin1); read(tin2);
            addb(tin1,tin2);
            addb(tin2,tin1);
        }
        
        mem(le,-1); mem(d,-1);
        dfs(1);
        if(d[1]!=-1) ++ans;
        printf("%d
    ",ans);
    }
    T2

    T3 星空

    考试打的傻dp骗了80  2333333

    先说说考试的傻dp

    用背包dp预处理出$g_len$表示len这么长都覆盖一次需要的最小次数 (也可以bfs求拉)

    $f_i$ 表示前i个原先没亮的点都点亮,并且其他原先亮着的点也亮着 $f[8]$

    转移:

    找出连续的一段,枚举往左往右到哪,然后转移

    找出下一段连续的一段,这两段同时被点亮,转移

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    inline void read(int &x)
    {
        x=0; int ff=1; char q=getchar();
        while(q<'0'||q>'9') { if(q=='-') ff=-1; q=getchar(); }
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
        x*=ff;
    }
    
    int n,K,m;
    int len[106],pos[106];
    int g[80006];
    int f[106];
    
    void work12()
    {
        rint i; int ans=0;
        if(len[m]==1)
            ans=K;
        else
        {
            if(m==2)
            {
                for(i=1;i<=K;)
                {
                    if(pos[i]==pos[i+1]-1)
                        ++ans,i+=2;
                    else
                        ++ans,++i;
                }
            }
            else
            {
                for(i=1;i<=K;i+=2)
                  ans+=(pos[i+1]-pos[i]);
            }
        }
        printf("%d
    ",ans);
    }
    
    void work200()
    {
        rint i,j,k; int l1,r1,l2,r2,tt;
        mem(g,30);
        g[0]=0;
        for(i=1;i<=m;++i)
            for(j=n;j>=len[i];--j)
                if(g[j]>g[j-len[i]]+1)
                    g[j]=g[j-len[i]]+1;
        mem(f,30); f[0]=0;
        pos[K+1]=n+1;
        for(i=1;i<=K;++i)
        {
            l1=i; r1=l1+1; while(r1<=K&&pos[r1]==pos[r1-1]+1) ++r1; --r1;
            l2=r1+1; r2=l2+1; while(r2<=K&&pos[r2]==pos[r2-1]+1) ++r2; --r2;
            for(j=pos[l1];j>pos[l1-1];--j)
                for(k=pos[r1];k<pos[r1+1];++k)
                {
                    tt=g[k-j+1]+g[pos[l1]-j]+g[k-pos[r1]];
                    if(f[r1]>f[l1-1]+tt) f[r1]=f[l1-1]+tt;
                }
            if(l2<=K)
            {
                tt=g[pos[r2]-pos[l1]+1]+g[pos[l2]-pos[r1]-1];
                if(f[r2]>tt+f[l1-1]) f[r2]=tt+f[l1-1];
                tt=g[pos[l2]-pos[l1]]+g[pos[r2]-pos[r1]];
                if(f[r2]>tt+f[l1-1]) f[r2]=tt+f[l1-1];
            }
        }
        if(f[K]>100000) f[K]=K+m;
        printf("%d
    ",f[K]);
    }
    
    void work4e4()
    {
        rint i,j,k; int l1,r1,l2,r2,tt;
        mem(g,30);
        g[0]=0;
        for(i=1;i<=m;++i)
            for(j=n;j>=len[i];--j)
                if(g[j]>g[j-len[i]]+1)
                    g[j]=g[j-len[i]]+1;
        mem(f,30); f[0]=0;
        pos[K+1]=n+1; int ci;
        for(i=1;i<=K;++i)
        {
            l1=i; r1=l1+1; while(r1<=K&&pos[r1]==pos[r1-1]+1) ++r1; --r1;
            l2=r1+1; r2=l2+1; while(r2<=K&&pos[r2]==pos[r2-1]+1) ++r2; --r2;
            ci=0;
            for(j=pos[l1];j>pos[l1-1];--j)
            {
                ++ci; if(ci>60) break;
                for(k=pos[r1];k<pos[r1+1];++k)
                {
                    tt=g[k-j+1]+g[pos[l1]-j]+g[k-pos[r1]];
                    if(f[r1]>f[l1-1]+tt) f[r1]=f[l1-1]+tt;
                }
            }
            ci=0;
            for(k=pos[r1];k<pos[r1+1];++k)
            {
                ++ci; if(ci>60) break;
                for(j=pos[l1];j>pos[l1-1];--j)
                {
                    tt=g[k-j+1]+g[pos[l1]-j]+g[k-pos[r1]];
                    if(f[r1]>f[l1-1]+tt) f[r1]=f[l1-1]+tt;
                }
            }
            if(l2<=K)
            {
                tt=g[pos[r2]-pos[l1]+1]+g[pos[l2]-pos[r1]-1];
                if(f[r2]>tt+f[l1-1]) f[r2]=tt+f[l1-1];
                tt=g[pos[l2]-pos[l1]]+g[pos[r2]-pos[r1]];
                if(f[r2]>tt+f[l1-1]) f[r2]=tt+f[l1-1];
            }
        }
        if(f[K]>100000) f[K]=K+m;
        printf("%d
    ",f[K]);
    }
    
    int main(){
        
        //freopen("T3.in","r",stdin);
        
        //freopen("starlit.in","r",stdin);
        //freopen("starlit.out","w",stdout);
        
        rint i;
        
        read(n); read(K); read(m);
        for(i=1;i<=K;++i)
            read(pos[i]);
        sort(pos+1,pos+1+K);
        for(i=1;i<=m;++i)
            read(len[i]);
        sort(len+1,len+1+m);
        if(len[m]<=2)
            work12();
        else
            if(n<=200)
                work200();
        else
            work4e4();
    }
    T3傻dp

    正解

    设$A_i$表示原序列,规定1是灭,0是亮

    $B_i$是一个差分数组,$B_i=A_{i} ^ A_{i+1}$

    问题转化成 不超过$2*K$个1,两两配对,问最小花费和

    那么bfs预处理出来从一个1到另一个1的最小步数

    然后状压就行了

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <iostream>
    #include <algorithm>
    #define ll long long
    #define mem(a,b) memset(a,b,sizeof(a))
    #define rint register int
    using namespace std;
    inline void read(int &x)
    {
        x=0; int ff=1; char q=getchar();
        while(q<'0'||q>'9') { if(q=='-') ff=-1; q=getchar(); }
        while(q>='0'&&q<='9') x=x*10+q-'0',q=getchar();
        x*=ff;
    }
    
    int n,K,m,maxp;
    int len[106];
    int t[106],con;
    int A[40006],g[40006];
    int dis[36][36];
    
    int dui[300006],he,en;
    void get(int pp)
    {
        mem(g,30);
        g[pp]=0; he=1; en=0;
        dui[++en]=pp;
        int i,now;
        while(en>=he)
        {
            now=dui[he++];
            for(i=1;i<=m;++i)
            {
                if(now-len[i]>=0&&g[now-len[i]]>g[now]+1)
                {
                    g[now-len[i]]=g[now]+1;
                    dui[++en]=now-len[i];
                }
                if(now+len[i]<=n&&g[now+len[i]]>g[now]+1)
                {
                    g[now+len[i]]=g[now]+1;
                    dui[++en]=now+len[i];
                }
            }
        }
    }
    
    void bfs()
    {
        rint i,j;
        for(i=1;i<=con;++i)
        {
            get(t[i]);
            for(j=1;j<=con;++j)
                dis[i][j]=g[t[j]];
        }
    }
    
    int f[(1<<16)+100];
    int dp()
    {
        maxp=(1<<con)-1;
        mem(f,30); f[maxp]=0;
        rint i,j,k;
        for(i=maxp;~i;--i)
            for(j=1;j<=con;++j)
                for(k=j+1;k<=con;++k)
                    if( ((1<<(j-1))&i) && ((1<<(k-1))&i) && f[i^(1<<(j-1))^(1<<(k-1))]>f[i]+dis[j][k] )
                        f[i^(1<<(j-1))^(1<<(k-1))]=f[i]+dis[j][k];
        return f[0];
    }
    
    int main(){
        
        //freopen("T3.in","r",stdin);
        
        rint i; int tin;
        
        read(n); read(K); read(m);
        for(i=1;i<=K;++i)
            read(tin),A[tin]=1;
        for(i=1;i<=m;++i)
            read(len[i]);
        for(i=0;i<=n;++i)
            if( A[i]^A[i+1] )
                t[++con]=i;
        
        bfs();
        printf("%d
    ",dp());
    }
    T3正解
  • 相关阅读:
    JavaFx在macOS下的文字渲染Bug
    Java多接口同名方法的冲突
    旧技术的惯性
    一点思考(1)
    slisp:编译到JVM平台上的lisp方言
    Arcee:又一个 Parser Generator 轮子
    使用Java实现一门简单的动态语言
    Hello World!
    [NOI2008]奥运物流
    [IOI2005]Riv河流
  • 原文地址:https://www.cnblogs.com/A-LEAF/p/7791501.html
Copyright © 2020-2023  润新知