zoukankan      html  css  js  c++  java
  • FR #13题解

    A.

      有点像学军中学的一道NOIP模拟赛的题。因为插入的顺序唯一,然后就完了。。。

         具体操作是在线段树上二分,然后区间赋值1等等。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<vector>
    #define maxv 100500
    #define maxe 200500
    using namespace std;
    int n,q,x,y,g[maxv],nume=1,w[maxv],fw[maxv],dis[maxv],cnt=0,tot=0,anc[maxv][20],val[maxv];
    int ls[maxv<<2],rs[maxv<<2],lazy[maxv<<2],sum[maxv<<2],root,tr_root;
    int t=0;
    struct status
    {
        int id,val;
        status (int id,int val):id(id),val(val) {}
        status () {}
    };
    vector <status> v[maxv];
    struct edge
    {
        int v,nxt;
    }e[maxe];
    bool cmp(status x,status y) {return x.val<y.val;}
    void addedge(int u,int v)
    {
        e[++nume].v=v;e[nume].nxt=g[u];
        g[u]=nume;
    }
    void dfs1(int x)
    {
        val[x]=x;
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (v!=anc[x][0])
            {
                anc[v][0]=x;dis[v]=dis[x]+1;
                dfs1(v);
                val[x]=min(val[x],val[v]);    
            }
        }
    }
    void dfs2(int x)
    {
        for (int i=g[x];i;i=e[i].nxt)
        {
            int vs=e[i].v;
            if (vs==anc[x][0]) continue;
            v[x].push_back(status(vs,val[vs]));
        }
        sort(v[x].begin(),v[x].end(),cmp);
        for (int i=0;i<v[x].size();i++) dfs2(v[x][i].id);
        w[x]=++cnt;fw[cnt]=x;
    }
    void build(int &now,int left,int right)
    {
        now=++tot;sum[now]=lazy[now]=0;
        if (left==right) return;
        int mid=(left+right)>>1;
        build(ls[now],left,mid);
        build(rs[now],mid+1,right);
    }
    void pushdown(int now,int left,int right)
    {
        if (!lazy[now]) return;
        lazy[ls[now]]=lazy[rs[now]]=1;lazy[now]=0;
        int mid=(left+right)>>1;
        sum[ls[now]]=mid-left+1;sum[rs[now]]=right-mid;
    }
    int modify1(int now,int left,int right,int k)
    {
        pushdown(now,left,right);
        if (left==right) {sum[now]=1;return fw[left];}
        int mid=(left+right)>>1,r=(mid-left+1-sum[ls[now]]),ret;
        if (k>r) sum[ls[now]]=mid-left+1,lazy[ls[now]]=1;
        if (k>r) ret=modify1(rs[now],mid+1,right,k-r);
        else ret=modify1(ls[now],left,mid,k);
        sum[now]=sum[ls[now]]+sum[rs[now]];
        return ret;
    }
    int ask(int now,int left,int right,int pos)
    {
        if (!pos) return 0;
        pushdown(now,left,right);
        if (left==right) return sum[now];
        int mid=(left+right)>>1;
        if (pos<=mid) return ask(ls[now],left,mid,pos);
        else return ask(rs[now],mid+1,right,pos);
    }
    void modify2(int now,int left,int right,int pos)
    {
        pushdown(now,left,right);
        if (left==right) {sum[now]=0;return;}
        int mid=(left+right)>>1;
        if (pos<=mid) modify2(ls[now],left,mid,pos);
        else modify2(rs[now],mid+1,right,pos);
        sum[now]=sum[ls[now]]+sum[rs[now]];
    }
    void work2()
    {
        int reg=y;
        for (int e=19;e>=0;e--)
        {
            int ret=ask(root,1,n,w[anc[y][e]]);
            if (ret) y=anc[y][e];
        }
        modify2(root,1,n,w[y]);
        printf("%d
    ",dis[reg]-dis[y]);
    }
    int main()
    {
        scanf("%d%d",&n,&q);
        for (int i=1;i<=n;i++)
        {
            scanf("%d",&x);
            if (!x) tr_root=i;
            else {addedge(x,i);addedge(i,x);}
        }
        dfs1(tr_root);dfs2(tr_root);
        for (int e=1;e<=19;e++)
            for (int i=1;i<=n;i++)
                anc[i][e]=anc[anc[i][e-1]][e-1];
        build(root,1,n);
        for (int i=1;i<=q;i++)
        {
            scanf("%d%d",&x,&y);
            if (x==1) printf("%d
    ",modify1(root,1,n,y));
            else work2();
        }
        return 0;
    }

    B.

      本来以为要用什么奇怪的自动机等等等等,然后。。。。

          设这个数位置是n。奇数长度?a[n]!=a[n-2]。否则?a[n]!=a[n-1]。

          然后数位dp一波就完了。。。

          注意判0。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    long long a,b,dp[20][10][10],ret=0,bit[20];
    void getbit(long long x)
    {
        ret=0;
        while (x)
        {
            bit[++ret]=x%10;
            x/=10;
        }
    }
    long long dfs(long long now,long long pre2,long long pre1,bool flag)
    {
        if (!now) return 1;
        if ((!flag) && (pre2!=-1) && (pre1!=-1) && (dp[now][pre2][pre1])) return dp[now][pre2][pre1];
        long long ret=0,up=flag?bit[now]:9;
        for (long long i=0;i<=up;i++)
        {
            if ((i!=pre2) && (i!=pre1))
                ret+=dfs(now-1,pre1,i,flag && (i==bit[now]));
        }
        if ((!flag) && (pre2!=-1) && (pre1!=-1)) dp[now][pre1][pre2]=ret;
        return ret;
    }
    long long ask(long long x)
    {
        if (x==-1) return 0;
        getbit(x);long long ans=0;
        for (long long i=1;i<=ret-1;i++)
            for (long long j=1;j<=9;j++)
                ans+=dfs(i-1,-1,j,0);
        for (long long i=1;i<=bit[ret]-1;i++)
            ans+=dfs(ret-1,-1,i,0);
        ans+=dfs(ret-1,-1,bit[ret],1);
        return ans;
    }
    int main()
    {
        scanf("%lld%lld",&a,&b);
        if (!a) {a++;printf("%lld
    ",ask(b)-ask(a-1)+1);}
        else printf("%lld
    ",ask(b)-ask(a-1));
        return 0;
    }

    C.

      m>n?肯定多解。。。

         m<n?废话。。。

         m=n?环套树。。。然后直接按环上解方程就行了。。。。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxv 100500
    #define maxe 1000050
    using namespace std;
    int n,m,x,y,c[maxv],g[maxv],nume=1,val[maxe],d[maxv];
    int top=0,flag2,flag3;
    bool vis[maxv],rol[maxv],flag1,flag4;
    struct edge
    {
        int v,nxt;
    }e[maxe];
    struct status
    {
        int id,id1,id2,val;
        status (int id,int id1,int id2,int val):id(id),id1(id1),id2(id2),val(val) {}
        status () {}
    }s[maxv];
    bool cmp(status x,status y) {return x.id<y.id;}
    void addedge(int u,int v)
    {
        e[++nume].v=v;e[nume].nxt=g[u];
        g[u]=nume;
    }
    void dfs1(int x,int fath,int fath_e)
    {
        int ret=0;
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if (v==fath) continue;
            dfs1(v,x,i);ret-=val[i>>1];
        }
        val[fath_e>>1]=c[x]+ret;
    }
    void dfs2(int x,int fath_e)
    {
        vis[x]=true;
        for (int i=g[x];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if ((vis[v]) && (i!=(fath_e^1)))
            {
                s[++top]=status(x,i>>1,fath_e>>1,c[x]);
                flag1=1;flag2=v;flag3=i;rol[x]=true;
                return;
            }
            if (vis[v]) continue;
            dfs2(v,i);
            if (flag1)
            {
                if (flag4) return;
                rol[x]=true;
                if (x!=flag2) s[++top]=status(x,i>>1,fath_e>>1,c[x]);
                else {s[++top]=status(x,i>>1,flag3>>1,c[x]);flag4=1;}
                return;
            }
        }
        return;
    }
    void work1()
    {
        dfs1(1,1,0);
        for (int i=1;i<=m;i++) printf("%d
    ",val[i]<<1);
        return;
    }
    void work2()
    {
        for (int i=1;i<=n;i++)
            if (d[i]==1)
                {dfs2(i,0);break;}
        if (!(top&1)) {printf("0
    ");return;}
        for (int i=1;i<=n;i++)
        {
            if (!rol[i]) continue;
            for (int j=g[i];j;j=e[j].nxt)
            {
                int v=e[j].v;
                if (rol[v]) continue;
                dfs1(v,i,j);c[i]-=val[j>>1];
            }
        }
        int ret=0;
        for (int i=1;i<=top-1;i++)
        {
            if (i&1) ret+=c[s[i].id];
            else ret-=c[s[i].id];
        }
        val[s[1].id1]=(ret+c[s[top].id])/2;
        for (int i=1;i<=top-1;i++)
            val[s[i].id2]=c[s[i].id]-val[s[i].id1];
        for (int i=1;i<=m;i++) printf("%d
    ",val[i]<<1);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++) scanf("%d",&c[i]);
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d",&x,&y);
            addedge(x,y);addedge(y,x);
            d[x]++;d[y]++;
        }
        if (m>n) printf("0
    ");
        else if (m<n) work1();
        else work2();
        return 0;
    }

    怎么说呢?。。。三道题都是,只要点出了它的核心都很简单。那么重点就是那一点点思维。

  • 相关阅读:
    windows下在命令行模式下使用MinGW编译C代码,出现cannot find ipthread
    Python入门系列——第4篇
    Python入门系列——第3篇
    python入门系列——第2篇
    Python入门系列——第1篇
    Python入门系列——第0篇
    PAT(乙级)1038
    WPF QuickStart系列之附加属性(Attached Property)
    WPF 自定义Metro Style窗体
    WPF QuickStart系列之数据绑定(Data Binding)
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6419376.html
Copyright © 2011-2022 走看看