zoukankan      html  css  js  c++  java
  • 【NOIP2013TG】solution

    链接:https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83%2C30

    D1T1:转圈游戏(circle)

    题意:看题目。。

    解题思路:快速幂求( (10^k m) mod n )即可。时间效率( O (lg k) )

    #include<stdio.h>
    #define ll long long
    #define For(i,a,b) for(int i=a; i<=b; i++)
    #define Ford(i,a,b) for(int i=a; i>=b; i--)
    #define File(fn) freopen(fn".in","r",stdin);freopen(fn".out","w",stdout);
    int n,m,k,x;
    inline int in(){
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    inline void print(int x,char ch){
        if (!x){
            putchar('0');
            putchar(ch);
            return;
        }
        if (x<0){
            putchar('-');
            x*=-1;
        }
        char num[10];
        short cnt=0;
        while(x) num[++cnt]=x%10+'0',x/=10;
        while(cnt) putchar(num[cnt--]);
        putchar(ch);
    }
    inline ll ksm(int a,int k){
        if (!k) return 1;
        if (!(k^1)) return a;
        ll t=ksm(a,k>>1)%n;
        t*=t;t%=n;
        if (k&1) t*=a;
        t%=n;
        return t;
    }
    int main(){
        n=in(),m=in(),k=in(),x=in();
        print((ksm(10,k)*m%n+x)%n,'
    ');
    }

    D1T2:火柴排队(match)

    题意:将一个数组中元素进行几次交换后使得这个数组的大小顺序与另一个数组相同。

    解题思路:离散后排序求逆序对数。时间效率( O(n lg n) ).

    #include<stdio.h>
    #include<algorithm>
    #define ll long long
    #define For(i,a,b) for(int i=a; i<=b; i++)
    #define Ford(i,a,b) for(int i=a; i>=b; i--)
    #define File(fn) freopen(fn".in","r",stdin);freopen(fn".out","w",stdout);
    #define mod 99999997
    using namespace std;
    struct zxy{
        int num,no;
    }a[100001],b[100001];
    int n,ans=0,c[100001],BIT[100001];
    inline int in(){
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    inline void print(int x,char ch){
        if (!x){
            putchar('0');
            putchar(ch);
            return;
        }
        if (x<0){
            putchar('-');
            x*=-1;
        }
        char num[10];
        short cnt=0;
        while(x) num[++cnt]=x%10+'0',x/=10;
        while(cnt) putchar(num[cnt--]);
        putchar(ch);
    }
    bool cmp(zxy a,zxy b){
        return a.num<b.num;
    }
    void init(){
        n=in();
        For(i,1,n) a[i].num=in(),a[i].no=i;
        For(i,1,n) b[i].num=in(),b[i].no=i;
        sort(a+1,a+n+1,cmp);
        sort(b+1,b+n+1,cmp);
        For(i,1,n) c[b[i].no]=a[i].no;
    }
    inline int lowbit(int k){
        return k&(-k);
    }
    inline void update(int x,int ad){
        while(x<=n){
            BIT[x]+=ad;
            x+=lowbit(x);
        }
    }
    inline int query(int x){
        int sum=0;
        while(x){
            sum+=BIT[x];
            x-=lowbit(x);
        }
        return sum;
    }
    void solve(){
        For(i,1,n){
            update(c[i],1);
            ans+=(i-query(c[i]));
            ans%=mod;
        }
        print(ans,'
    ');
    }
    int main(){
        init();
        solve();
        return 0;
    }

    D1T3:货车运输(truck)

    题意:给你一张图,问你从一个点到另一个点的路径上的最大的路径上最小的权值是多少,如果不能联通输出-1.

    解题思路:首先为了方便处理,我们将所有点向0号点连一条权值为-1的边,这样保证所有点可以联通的同时会输出答案-1.接下来,我们考虑题意要求的使得“最小的尽可能”大的条件,发现可以使用最大生成树实现,接下来考虑查询两点间的树上路径中权值最小的边,使用LCA即可作答,这里可以使用所有的LCA算法,我使用了理解与实现都较为容易倍增求LCA,时间效率为( O(m lg m+q lg n) )。

    附优化了各种常数的代码(貌似还可以继续优化)。

    #include<stdio.h>
    #include<algorithm>
    #define INF 0x7fffffff
    using namespace std;
    struct zxy{
        int x,y,l;
    }edge[150001];
    struct tree{
        int next,to,v;
    }tr[20005];
    int father[10001],fa[10001][15],n,m,q,cnt=0,used[10005],deep[10005],head[10005],dis[10001][15];
    inline int in(){
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    inline int find(int x){
        return father[x]=father[x]==x?x:find(father[x]);
    }
    bool cmp(zxy a,zxy b){
        return a.l>b.l;
    }
    inline void ins(int x,int y,int l){
        edge[++cnt].x=x,edge[cnt].y=y,edge[cnt].l=l;
    }
    inline void ins2(int x,int y,int l){
        tr[++cnt].to=y,tr[cnt].next=head[x],head[x]=cnt,tr[cnt].v=l;
    }
    void init(){
        n=in(),m=in();
        int x,y,l;
        for (int i=1; i<=m; ++i){
            x=in(),y=in(),l=in();
            ins(x,y,l);ins(y,x,l);
        }
    }
    bool mst(){
        for(register int i=1; i<=n; ++i)
            father[i]=i,ins(0,i,-1),ins(i,0,-1);
        sort(edge+1,edge+cnt+1,cmp);
        int k=0;
        for(register int i=1; i<=cnt; ++i)
            if (find(edge[i].x)!=find(edge[i].y)){
                father[find(father[edge[i].x])]=find(edge[i].y);
                used[++k]=i;        
            }
        cnt=0;
        for(register int i=1; i<=k; ++i) 
            ins2(edge[used[i]].x,edge[used[i]].y,edge[used[i]].l),ins2(edge[used[i]].y,edge[used[i]].x,edge[used[i]].l);
        return !(k^n);
    }
    inline void dfs(int x,int d,int f){
        deep[x]=d;fa[x][0]=f;
        for (register int i=head[x]; i; i=tr[i].next)
            if (tr[i].to!=f) dis[tr[i].to][0]=tr[i].v,dfs(tr[i].to,d+1,x);
    }
    void init_LCA(){
        for(int j=1; j<=14; ++j)    
            for(register int i=0; i<=n; ++i)
                fa[i][j]=fa[fa[i][j-1]][j-1],dis[i][j]=min(dis[i][j-1],dis[fa[i][j-1]][j-1]);
    }
    inline int query(int x,int y){
        if (deep[x]<deep[y]){int t=x;x=y,y=t;}
        int mi=INF,d=deep[x]-deep[y];
        if (d) for(register int i=0; d&&i<=14; ++i,d>>=1) if (d&1) mi=min(mi,dis[x][i]),x=fa[x][i];
        if (!(x^y)) return mi;
        for(register int i=14; i>=0; --i) if (fa[x][i]!=fa[y][i]) mi=min(mi,min(dis[x][i],dis[y][i])),x=fa[x][i],y=fa[y][i];
        mi=min(mi,min(dis[x][0],dis[y][0]));
        return mi;
    }
    void lca(){
        q=in();
        dfs(0,0,0);init_LCA();
        for(register int i=1; i<=q; ++i){
            register int x=in(),y=in();
            printf("%d
    ",query(x,y));
        }
    }
    int main(){
        init();
        mst();
        lca();
        return 0;
    }

    D2T1:积木大赛(block)

    题意:看题目。。

    解题思路:暴力模拟,具体见代码。时间效率(O(n))。

    #include<stdio.h>
    #define ll long long
    #define For(i,a,b) for(int i=a; i<=b; i++)
    #define Ford(i,a,b) for(int i=a; i>=b; i--)
    #define File(fn) freopen(fn".in","r",stdin);freopen(fn".out","w",stdout);
    int a[100001],n,h,t,ans;
    inline int in(){
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    inline void print(int x,char ch){
        if (!x){
            putchar('0');
            putchar(ch);
            return;
        }
        if (x<0){
            putchar('-');
            x*=-1;
        }
        char num[10];short cnt=0;
        while(x) num[++cnt]=x%10+'0',x/=10;
        while(cnt) putchar(num[cnt--]);
        putchar(ch);
    }
    int main(){
        n=in();
        For(i,1,n) a[i]=in();
        h=0;
        For(i,1,n)
            if (a[i]<a[i-1]) ans+=a[i-1]-a[h],h=i;
        ans+=a[n]-a[h];
        print(ans,'
    ');
    }

     D2T2:花匠(flower)

    题意:看题目啊。。。

    解题思路:显然题目就是叫你找一个最长的连续上升子序列/下降子序列,所以乱搞一下就好了。时间效率(O(n)).

    #include<stdio.h>
    #define ll long long
    #define For(i,a,b) for(int i=a; i<=b; i++)
    #define Ford(i,a,b) for(int i=a; i>=b; i--)
    #define File(fn) freopen(fn".in","r",stdin);freopen(fn".out","w",stdout);
    int a[100001],ans=1,flag=-1,n;
    inline int in(){
        int x=0,f=1;
        char ch=getchar();
        while(ch<'0'||ch>'9') f=ch=='-'?-1:1,ch=getchar();
        while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    inline void print(int x,char ch){
        if (!x){
            putchar('0');
            putchar(ch);
            return;
        }
        if (x<0){
            putchar('-');
            x*=-1;
        }
        char num[10];
        short cnt=0;
        while(x) num[++cnt]=x%10+'0',x/=10;
        while(cnt) putchar(num[cnt--]);
        putchar(ch);
    }
    int main(){
        n=in();
        For(i,1,n) a[i]=in();
        For(i,2,n){
            if (a[i]>a[i-1]&&(flag-1)) ans++,flag=1;
            if (a[i]<a[i-1]&&flag) ans++,flag=0;
        }
        print(ans,'
    ');
    }

     本文由Melacau编写,Melacau代表M星向您问好,如果您不是在我的博客http://www.cnblogs.com/Melacau上看到本文,请您向我联系,email:13960948839@163.com.

  • 相关阅读:
    分化Oracle数据库日记文件(1)
    ORACLE稀有错误代码的阐发与经管(二)
    Oracle暗码文件的运用和维护
    在ORACLE中移动数据库文件
    ORACLE8的分区管理
    Oracle中如何间接运转OS号令(上)
    Oracle数据库平安计谋阐明 (三)
    Oracle7.X 回滚表空间数据文件误删除措置举动措施
    Oracle功用究极优化 中
    网络知识爆炸的年代~如何更好地学习吸收有用的知识
  • 原文地址:https://www.cnblogs.com/Melacau/p/NOIPTG2013solution.html
Copyright © 2011-2022 走看看