1. 程式人生 > >10.12 兩次考試

10.12 兩次考試

ems color clas bzoj cmp -a add clu void

上午的有些不可做...

等我成神犇之後再說吧...

下午的:

T1

原題bzoj網格

技術分享
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int mod=20100403;
const
int N=3000006; ll qpow(ll a,int ci) { ll ans=1; while(ci) { if(ci&1) ans=ans*a%mod; a=a*a%mod; ci>>=1; } return ans; } ll jie[N],jieni[N]; void chu() { jie[0]=1; for(int i=1;i<N;++i) jie[i]=jie[i-1]*i%mod; jieni[N
-1]=qpow(jie[N-1],mod-2)%mod; for(int i=N-2;i>=1;--i) jieni[i]=jieni[i+1]*(ll)(i+1)%mod; jieni[0]=1; } int n,m; inline ll C(int n,int m) { if(n<0||m<0) return 0; if(n<m) return 0; return jie[n]*jieni[m]%mod*jieni[n-m]%mod; } int main(){ chu(); scanf(
"%d%d",&n,&m); printf("%lld", (C(n+m,n)-C(n+m,n+1)+mod)%mod ); }
T1

T2

首先預處理出來$c_i$為第i口井可以喝的次數

當前飛到第j次,ans為前j-1次喝到的水,$nu_i$為第i口井前面可以喝的井的數目

那麽第j次第i口井能喝到水,它必須滿足 $c_i$-$nu_i$>ans

那麽我們用線段樹維護$c_i$-$nu_i$的最小值

到了第j次飛,我們就把線段樹中$c_i$-$nu_i$<=ans的都取出來去掉,並且把i+1~n的值都+1

一直到第m次或沒有滿足條件的井了

技術分享
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<0||q>9)q=getchar();
    while(q>=0&&q<=9){ans=ans*10+q-0;q=getchar();}
    return ans;
}
const int N=100006;
const int INF=0x7fffffff-1e8;

int n,m;
int hi;
int w[N],A[N],ci[N];

struct TTT______TTT
{
    int mn[N*5],sum[N*5];
    int ji[N*5];
    inline void pushup(int x)
    {
        sum[x]=sum[x<<1]+sum[x<<1|1];
        mn[x]=(mn[x<<1]<mn[x<<1|1]?mn[x<<1]:mn[x<<1|1]);
    }
    void pushdown(int x)
    {
        if(ji[x])
        {
            ji[x<<1]+=ji[x];
            ji[x<<1|1]+=ji[x];
            mn[x<<1]+=ji[x];
            mn[x<<1|1]+=ji[x];
            ji[x]=0;
        }
    }
    void build(int l,int r,int x)
    {
        if(l==r)
        {
            mn[x]=ci[l]-l+1,sum[x]=1;
            return ;
        }
        int mid=(l+r)>>1;
        build(l,mid,x<<1);
        build(mid+1,r,x<<1|1);
        pushup(x);
    }
    void del(int pos,int l,int r,int x)
    {
        if(l==r)
        {
            mn[x]=INF;sum[x]=0;
            return ;
        }
        pushdown(x);
        int mid=(l+r)>>1;
        if(pos<=mid)
            del(pos,l,mid,x<<1);
        else
            del(pos,mid+1,r,x<<1|1);
        pushup(x);
    }
    void add(int L,int R,int l,int r,int x)
    {
        if(L>R)
            return ;
        if(L<=l&&r<=R)
        {
            ++mn[x];++ji[x];
            return ;
        }
        pushdown(x);
        int mid=(l+r)>>1;
        if(L<=mid)
            add(L,R,l,mid,x<<1);
        if(mid<R)
            add(L,R,mid+1,r,x<<1|1);
        pushup(x);
    }
    int qqpos(int val,int l,int r,int x)
    {
        if(l==r)
            return l;
        pushdown(x);
        int mid=(l+r)>>1;
        if(mn[x<<1]==val)
            return qqpos(val,l,mid,x<<1);
        else
            return qqpos(val,mid+1,r,x<<1|1);
    }
}T;

int work()
{
    T.build(1,n,1);
    int ans=0,temp;
    for(int i=1;i<=m;++i)
    {
        //printf("i=%d ans=%d\n",i,ans);

        while(T.mn[1]<=ans)
        {
            temp=T.qqpos(T.mn[1],1,n,1);
            //printf("mn=%d pos=%d\n",T.mn[1],temp);
            T.del(temp,1,n,1);
            T.add(temp+1,n,1,n,1);
            //cout<<0;
        }
        ans+=T.sum[1];
        if(T.sum[1]==0)
            break;
    }
    return ans;
}

int main(){

    freopen("T2.in","r",stdin);
    freopen("T2.out","w",stdout);

    n=read();m=read();hi=read();
    for(int i=1;i<=n;++i)
        w[i]=read();
    for(int i=1;i<=n;++i)
        A[i]=read();
    for(int i=1;i<=n;++i)
    {
        ci[i]=(hi-w[i])/A[i]+1;
        if(ci[i]<0)
            ci[i]=0;
    }

    /*printf("\n");
    for(int i=1;i<=n;++i)
        printf("%d ",ci[i]);
    printf("\n");*/

    cout<<work();
}
T2

T3

先把op==1||op==2的同一行(列)的並查集並起來,這樣可以減小建邊數量

然後tarjan一下,求最長鏈即可

技術分享
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
inline int read()
{
    char q=getchar();int ans=0;
    while(q<0||q>9)q=getchar();
    while(q>=0&&q<=9){ans=ans*10+q-0;q=getchar();}
    return ans;
}
const int N=100006;
const int RR=1000006;
const int CC=1000006;
struct son
{
    int v,next;
};
struct TTT___TTT
{
    son a1[N*10];
    int first[N*10],e;
    void clear()
    {
        mem(a1,0);
        mem(first,-1);
        e=0;
    }
    void addbian(int u,int v)
    {
        a1[e].v=v;
        a1[e].next=first[u];
        first[u]=e++;
    }
}h[2];
struct JI
{
    int x,y,jian,jia,order;
    int op;
    void boom()
    {
        x=y=jian=jia=op=0x7fffffff;
        order=0;
    }
}ji[N];
bool cmp_x(JI a,JI b)
{
    if(a.x==b.x)
        return a.y<b.y;
    return a.x<b.x;
}
bool cmp_y(JI a,JI b)
{
    if(a.y==b.y)
        return a.x<b.x;
    return a.y<b.y;
}
bool cmp_jian(JI a,JI b)
{
    if(a.jian==b.jian)
        return a.jia<b.jia;
    return a.jian<b.jian;
}
bool cmp_jia(JI a,JI b)
{
    if(a.jia==b.jia)
        return a.jian<b.jian;
    return a.jia<b.jia;
}

int fa[N];
int fin(int x)
{
    if(fa[x]==-1)
        return x;
    fa[x]=fin(fa[x]);
    return fa[x];
}
void match(int u,int v)
{
    int x=fin(u),y=fin(v);
    if(x!=y)
        fa[x]=y;
}

int n,R,C;

int zhan[N*5],he;
int num[N];

int dfn[N],low[N],tim;
bool flag[N];
int sum,sun[N],dui[N];

int an[N];

void dfs(int x)
{
    int temp;
    an[x]=sun[x];
    for(int i=h[1].first[x];i!=-1;i=h[1].a1[i].next)
    {
        temp=h[1].a1[i].v;
        if(an[temp])
        {
            if(an[x]<an[temp]+sun[x])
                an[x]=an[temp]+sun[x];
            continue;
        }
        dfs(temp);
        if(an[x]<an[temp]+sun[x])
            an[x]=an[temp]+sun[x];
    }
}

void tarjan(int x)
{
    dfn[x]=low[x]=++tim;
    zhan[++he]=x;flag[x]=1;
    int temp;
    for(int i=h[0].first[x];i!=-1;i=h[0].a1[i].next)
    {
        temp=h[0].a1[i].v;
        if(dfn[temp]==-1)
        {
            tarjan(temp);
            if(low[x]>low[temp])
                low[x]=low[temp];
        }
        else
            if(flag[temp]&&low[x]>low[temp])
                low[x]=low[temp];
    }
    if(low[x]==dfn[x])
    {
        ++sum;
        while(1)
        {
            temp=zhan[he--];flag[temp]=0;
            dui[temp]=sum;
            sun[sum]+=num[temp];
            if(temp==x)
                break;
        }
    }
}

void out11()
{
    /*printf("\n");
    for(int i=1;i<=n;++i)
        printf("%d ",fin(i));
    printf("\n");*/
    printf("\n");
    for(int i=1;i<=n;++i)
    {
        printf("i=%d  ",i);
        for(int j=h[0].first[i];j!=-1;j=h[0].a1[j].next)
            printf("%d ",h[0].a1[j].v);
        printf("\n");
    }
    printf("\n");
}

int work()
{
    ji[0].boom();ji[n+1].boom();



    sort(ji+1,ji+1+n,cmp_x);
    int now,t1,t2;
    for(int i=1;i<=n;i=now+1)
    {
        now=i;he=0;
        while(ji[now].x==ji[i].x&&now<=n)
        {
            if( ji[now].op==1 )
                zhan[++he]=now;
            ++now;
        }
        --now;
        for(int j=2;j<=he;++j)
            match(ji[zhan[j]].order,ji[zhan[j-1]].order);
    }
    sort(ji+1,ji+1+n,cmp_y);
    for(int i=1;i<=n;i=now+1)
    {
        now=i;he=0;
        while(ji[now].y==ji[i].y&&now<=n)
        {
            if( ji[now].op==2 )
                zhan[++he]=now;
            ++now;
        }
        --now;
        for(int j=2;j<=he;++j)
            match(ji[zhan[j]].order,ji[zhan[j-1]].order);
    }



    sort(ji+1,ji+1+n,cmp_x);
    for(int i=1;i<=n;i=now+1)
    {
        now=i;he=0;
        while(ji[now].x==ji[i].x&&now<=n)
        {
            if( ji[now].op==1 )
                zhan[++he]=now;
            ++now;
        }
        --now;
        if(he)
        {
            t1=fin(ji[zhan[1]].order);
            for(int j=i;j<=now;++j)
            {
                t2=fin(ji[j].order);
                if(t1!=t2)
                    h[0].addbian(t1,t2);
            }
        }
        for(int j=i;j<=now;++j)
            if(ji[j].op==3)
            {
                if(ji[j-1].x==ji[j].x&&ji[j-1].y==ji[j].y-1&&fin(ji[j].order)!=fin(ji[j-1].order))
                    h[0].addbian(fin(ji[j].order),fin(ji[j-1].order));
                if(ji[j+1].x==ji[j].x&&ji[j+1].y==ji[j].y+1&&fin(ji[j].order)!=fin(ji[j+1].order))
                    h[0].addbian(fin(ji[j].order),fin(ji[j+1].order));
            }
    }

    sort(ji+1,ji+1+n,cmp_y);
    for(int i=1;i<=n;i=now+1)
    {
        now=i;he=0;
        while(ji[now].y==ji[i].y&&now<=n)
        {
            if( ji[now].op==2 )
                zhan[++he]=now;
            ++now;
        }
        --now;
        if(he)
        {
            t1=fin(ji[zhan[1]].order);
            for(int j=i;j<=now;++j)
            {
                t2=fin(ji[j].order);
                if(t1!=t2)
                    h[0].addbian(t1,t2);
            }
        }
        for(int j=i;j<=now;++j)
            if(ji[j].op==3)
            {
                if(ji[j-1].y==ji[j].y&&ji[j-1].x==ji[j].x-1&&fin(ji[j].order)!=fin(ji[j-1].order))
                    h[0].addbian(fin(ji[j].order),fin(ji[j-1].order));
                if(ji[j+1].y==ji[j].y&&ji[j+1].x==ji[j].x+1&&fin(ji[j].order)!=fin(ji[j+1].order))
                    h[0].addbian(fin(ji[j].order),fin(ji[j+1].order));
            }
    }

    sort(ji+1,ji+1+n,cmp_jian);
    for(int i=1;i<=n;++i)
        if(ji[i].op==3)
        {
            t1=fin(ji[i].order);
            t2=fin(ji[i-1].order);
            if(ji[i-1].jian==ji[i].jian&&ji[i-1].jia==ji[i].jia-2&&t1!=t2)
                h[0].addbian(t1,t2);
            t2=fin(ji[i+1].order);
            if(ji[i+1].jian==ji[i].jian&&ji[i+1].jia==ji[i].jia+2&&t1!=t2)
                h[0].addbian(t1,t2);
        }
    sort(ji+1,ji+1+n,cmp_jia);
    for(int i=1;i<=n;++i)
        if(ji[i].op==3)
        {
            t1=fin(ji[i].order);
            t2=fin(ji[i-1].order);
            if(ji[i-1].jia==ji[i].jia&&ji[i-1].jian==ji[i].jian-2&&t1!=t2)
                h[0].addbian(t1,t2);
            t2=fin(ji[i+1].order);
            if(ji[i+1].jia==ji[i].jia&&ji[i+1].jian==ji[i].jian+2&&t1!=t2)
                h[0].addbian(t1,t2);
        }

    for(int i=1;i<=n;++i)
        ++num[fin(i)];
    he=0;
    for(int i=1;i<=n;++i)
        if(dfn[i]==-1&&num[i])
            tarjan(i);
    int temp;
    for(int i=1;i<=n;++i)
        if(num[i])
        {
            for(int j=h[0].first[i];j!=-1;j=h[0].a1[j].next)
            {
                temp=h[0].a1[j].v;
                if(dui[i]!=dui[temp])
                    h[1].addbian(dui[i],dui[temp]);
            }
        }

    //out11();

    //printf("sum=%d\n",sum);

    for(int i=1;i<=sum;++i)
        if(!an[i])
            dfs(i);
    int ans=0;
    for(int i=1;i<=sum;++i)
        if(ans<an[i])
            ans=an[i];
    return ans;
}

int main(){

    //freopen("T3.in","r",stdin);

    mem(fa,-1);
    mem(dfn,-1);
    h[0].clear();
    h[1].clear();

    n=read();R=read();C=read();
    for(int i=1;i<=n;++i)
    {
        ji[i].x=read();
        ji[i].y=read();
        ji[i].op=read();
        ji[i].jia=ji[i].x+ji[i].y;
        ji[i].jian=ji[i].x-ji[i].y;
        ji[i].order=i;
    }

    /*printf("\n");
    for(int i=1;i<=n;++i)
        printf("%d %d %d\n",ji[i].x,ji[i].y,ji[i].op);
    printf("\n");*/

    cout<<work();
}
T3

總結:

多考慮每個題成立的條件,不要無頭緒的亂想

還有打程序要嚴謹...一遍對...

10.12 兩次考試