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\n",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("\n");
    
    /*if(fb)
    {
        for(i=rb;i>=lb;--i)
            printf("%c",B[i]);
    }
    else
    {
        for(i=lb;i<=rb;++i)
            printf("%c",B[i]);
    }
    printf("\n");*/
}

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("\n");
    for(i=1;i<=lena;++i)
        printf("%c",A[i]);
    printf("\n");*/
    
    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\n",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\n",ans);
//    printf("\n%d\n",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\n",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\n",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\n",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\n",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\n",dp());
}
T3正解

 

posted @ 2017-11-06 08:18  A_LEAF  阅读(233)  评论(0编辑  收藏  举报