• 开学后的第一篇


    漫长(并不)而充实(未必)的寒假终于结束了。又是新学期的竞赛课程。看着满机房的学弟学妹们,心中澎湃万分。

    回归正题,回来第三天了,捡这三天做的比较好的题目写新学期的第一篇博客,勉励自己在OI的不归路上再接再厉。

    并不难(异常简单)的一题,但第一时间硬是没想到——原因是在假期听了许多节数据结构课,导致看到区间询问就想到线段树,花了5分钟打完后发现不对,10亿的范围连数组都开不出来。正解应该是:排序,二分查找一个询问中两端的位置,相减的区间内谷堆数量。代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    int n,q,a[100100];
    int comp(const int&a,const int&b){
        return a<b;
    }
    int search(int l,int r){
        int la=1;
        int ra=n;
        int mida=(la+ra)/2;
        while(!(a[mida]>=l&&a[mida-1]<l)){
            if(a[mida]>=l){
                ra=mida-1;
                mida=(la+ra)/2;
            }
            else{
                la=mida+1;
                mida=(la+ra)/2;
            }
            //cout<<la<<" "<<ra<<endl;
            if(la>=ra)break;
        }
        int lb=1;
        int rb=n;
        int midb=(lb+rb)/2;
        while(!(a[midb]<=r&&a[midb+1]>r)){
            if(a[midb]<=r){
                lb=midb+1;
                midb=(lb+rb)/2;
            }
            else{
                rb=midb-1;
                midb=(lb+rb)/2;
            }
            //cout<<lb<<" "<<rb<<endl;
            if(lb>=rb)break;
        }
        return midb-mida+1;
    }
    int main(){
        freopen("haybales.in","r",stdin);
        freopen("haybales.out","w",stdout); 
        cin>>n>>q;
        for(int i=1;i<=n;++i)scanf("%d",&a[i]);
        sort(a+1,a+n+1,comp);
        for(int i=1;i<=q;++i){
            int l,r;
            scanf("%d%d",&l,&r);
            if(l>a[n]||r<a[1]){
                cout<<0<<endl;
                continue;
            }
            printf("%d
    ",search(l,r));
        }
        return 0;
    }

    上面这道题目给出的教训是,不要想当然。

    乍一看都能想到N方的算法。细想不难发现有用的字段最多有26乘以26=676种,因此可以做一个有676个点的图。以城市名称的前两位为起点,州代码为终点加单向边,最后两两统计点与点之间两种单向边的乘积,累加即可。(PS:题目描述不是很明确,按照测试数据如果有两个ABAB的城市,不视为互有特殊关系)。代码如下(。。。尴尬,代码好像被我搞丢了,不管了,下一题)

    第一眼递推,但只能得到30分。正解须涉及到矩阵乘法。(可以在网上找找“矩阵乘法求斐波那契数列”),原理类似。乘积部分应用快速幂。代码如下

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include <list>            //STL 线性列表容器
    #include <map>       //STL 映射容器
    #include <queue>      //STL 队列容器
    #include <set>       //STL 集合容器
    #include <stack>      //STL 堆栈容器
    using namespace std;
    
    inline int read(){
        char ch=getchar();
        int re=0;
        bool fl=1;
        if (ch=='-'){
            re=0;
            ch=getchar();
        }
        while (ch>='0'&&ch<='9'){
            re=re*10+ch-'0';
            ch=getchar();
        }
        return fl?re:-re;
    }
    
    long long bas[4][4],ans[4][4],now[4][4],n,t,c;
    void getjz(int k){
        if(k==1){
            for(int i=1;i<=3;++i)
            for(int j=1;j<=3;++j)ans[i][j]=bas[i][j];
            return;
        }
        if(k%2==0){
            getjz(k/2);
            now[1][1]=(ans[1][1]*ans[1][1]%c+ans[1][2]*ans[2][1]%c+ans[1][3]*ans[3][1]%c)%c;
            now[1][2]=(ans[1][1]*ans[1][2]%c+ans[1][2]*ans[2][2]%c+ans[1][3]*ans[3][2]%c)%c;
            now[1][3]=(ans[1][1]*ans[1][3]%c+ans[1][2]*ans[2][3]%c+ans[1][3]*ans[3][3]%c)%c;
            now[2][1]=(ans[2][1]*ans[1][1]%c+ans[2][2]*ans[2][1]%c+ans[2][3]*ans[3][1]%c)%c;
            now[2][2]=(ans[2][1]*ans[1][2]%c+ans[2][2]*ans[2][2]%c+ans[2][3]*ans[3][2]%c)%c;
            now[2][3]=(ans[2][1]*ans[1][3]%c+ans[2][2]*ans[2][3]%c+ans[2][3]*ans[3][3]%c)%c;
            now[3][1]=(ans[3][1]*ans[1][1]%c+ans[3][2]*ans[2][1]%c+ans[3][3]*ans[3][1]%c)%c;
            now[3][2]=(ans[3][1]*ans[1][2]%c+ans[3][2]*ans[2][2]%c+ans[3][3]*ans[3][2]%c)%c;
            now[3][3]=(ans[3][1]*ans[1][3]%c+ans[3][2]*ans[2][3]%c+ans[3][3]*ans[3][3]%c)%c;
            for(int i=1;i<=3;++i)
            for(int j=1;j<=3;++j){
                //cout<<now[i][j]<<" ";
                //if(j==3)cout<<endl;
                ans[i][j]=now[i][j];
            }
            return;
        }
        if(k%2!=0){
            getjz(k-1);
            now[1][1]=(ans[1][1]*bas[1][1]%c+ans[1][2]*bas[2][1]%c+ans[1][3]*bas[3][1]%c)%c;
            now[1][2]=(ans[1][1]*bas[1][2]%c+ans[1][2]*bas[2][2]%c+ans[1][3]*bas[3][2]%c)%c;
            now[1][3]=(ans[1][1]*bas[1][3]%c+ans[1][2]*bas[2][3]%c+ans[1][3]*bas[3][3]%c)%c;
            now[2][1]=(ans[2][1]*bas[1][1]%c+ans[2][2]*bas[2][1]%c+ans[2][3]*bas[3][1]%c)%c;
            now[2][2]=(ans[2][1]*bas[1][2]%c+ans[2][2]*bas[2][2]%c+ans[2][3]*bas[3][2]%c)%c;
            now[2][3]=(ans[2][1]*bas[1][3]%c+ans[2][2]*bas[2][3]%c+ans[2][3]*bas[3][3]%c)%c;
            now[3][1]=(ans[3][1]*bas[1][1]%c+ans[3][2]*bas[2][1]%c+ans[3][3]*bas[3][1]%c)%c;
            now[3][2]=(ans[3][1]*bas[1][2]%c+ans[3][2]*bas[2][2]%c+ans[3][3]*bas[3][2]%c)%c;
            now[3][3]=(ans[3][1]*bas[1][3]%c+ans[3][2]*bas[2][3]%c+ans[3][3]*bas[3][3]%c)%c;
            for(int i=1;i<=3;++i)
            for(int j=1;j<=3;++j){
                //cout<<now[i][j]<<" ";
                //if(j==3)cout<<endl;
                ans[i][j]=now[i][j];
            }
            return;
        }
    }
    int main(){
        freopen("seq.in","r",stdin);
        freopen("seq.out","w",stdout);
        c=1000000007;
        scanf("%d",&t);
        bas[1][1]=1;
        bas[1][2]=0;
        bas[1][3]=1;
        bas[2][1]=1;
        bas[2][2]=0;
        bas[2][3]=0;
        bas[3][1]=0;
        bas[3][2]=1;
        bas[3][3]=0;
        for(int i=1;i<=t;++i){
            int k;
            scanf("%d",&k);
            for(int i=1;i<=3;++i)
            for(int j=1;j<=3;++j)ans[i][j]=0;
            if(k>3){
                getjz(k-3);
                //int final=
                printf("%d
    ",(ans[1][1]+ans[1][2]+ans[1][3])%c);
            }
            else printf("%d
    ",1);
        }
    
        return 0;
    }

    最后跑一个稍微复杂一点的

    第一眼DP,但是超规模了,60分。题干中说这不是一个简单的最短路问题——那就是不简单的最短路问题。将每个点拆成两个点即可。注意点X,Y相通时,是X与Y+N相连,X+N与Y相连。还有,X与X+N之间有距离。最短路我用的是SPFA,没有负边权的情况下也可用迪杰斯特拉(Dijkstra)。代码如下:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<string>
    #include<cmath>
    #include <list>            //STL 线性列表容器
    #include <map>       //STL 映射容器
    #include <queue>      //STL 队列容器
    #include <set>       //STL 集合容器
    #include <stack>      //STL 堆栈容器
    using namespace std;
    
    queue<int>q1;
    long long d[10100];
    int m,n,lnum,head[10100],dis[10100];
    bool tt[10100];
    inline int read(){
        char ch=getchar();
        int re=0;
        bool fl=1;
        if (ch=='-'){
            re=0;
            ch=getchar();
        }
        while (ch>='0'&&ch<='9'){
            re=re*10+ch-'0';
            ch=getchar();
        }
        return fl?re:-re;
    }
    
    struct star{
        int type;
        int w;
        int s;
    };  star c[10100];
    
    struct line{
        int power;
        int goal;
        int next;
    };  line ll[100010];
    
    int main(){
        freopen("holes.in","r",stdin);
        freopen("holes.out","w",stdout);
        n=read(); m=read();
        for(int i=1;i<=n;++i){
            int x; x=read();
            c[i].type=x;
            c[i+n].type=abs(1-x);
        }
        for(int i=1;i<=n;++i){
            int x; x=read();
            c[i].w=x; c[i+n].w=x;
        }
        for(int i=1;i<=n;++i){
            int x; x=read();
            c[i].s=x; c[i+n].s=x;
        }
        lnum=0;
        for(int i=1;i<=n;++i){
            if(c[i].type==0){
                lnum++;
                ll[lnum].goal=i+n;
                ll[lnum].power=0;
                ll[lnum].next=head[i];
                head[i]=lnum;
                lnum++;
                ll[lnum].goal=i;
                ll[lnum].power=c[i].s;
                ll[lnum].next=head[i+n];
                head[i+n]=lnum;
            }
            else{
                lnum++;
                ll[lnum].goal=i+n;
                ll[lnum].power=c[i].s;
                ll[lnum].next=head[i];
                head[i]=lnum;
                lnum++;
                ll[lnum].goal=i;
                ll[lnum].power=0;
                ll[lnum].next=head[i+n];
                head[i+n]=lnum;
            }
        }
        for(int i=1;i<=m;++i){
            int x,y,z;
            x=read(); y=read(); z=read();
            if(c[x].type==c[y].type){
                //cout<<x<<" "<<y<<endl;
                lnum++;
                ll[lnum].goal=y+n;
                ll[lnum].power=z;
                ll[lnum].next=head[x];
                head[x]=lnum;
                lnum++;
                ll[lnum].goal=y;
                ll[lnum].power=z;
                ll[lnum].next=head[x+n];
                head[x+n]=lnum;
            } 
            if((c[x].type==1)&&(c[y].type==0)){
                lnum++;
                ll[lnum].goal=y+n;
                ll[lnum].power=z+abs(c[x].w-c[y].w);
                ll[lnum].next=head[x];
                head[x]=lnum;
                lnum++;
                ll[lnum].goal=y;
                ll[lnum].power=max(0,z-abs(c[x].w-c[y].w));
                ll[lnum].next=head[x+n];
                head[x+n]=lnum;
            }
            if((c[x].type==0)&&(c[y].type==1)){
                lnum++;
                ll[lnum].goal=y+n;
                ll[lnum].power=max(0,z-abs(c[x].w-c[y].w));
                ll[lnum].next=head[x];
                head[x]=lnum;
                lnum++;
                ll[lnum].goal=y;
                ll[lnum].power=z+abs(c[x].w-c[y].w);
                ll[lnum].next=head[x+n];
                head[x+n]=lnum;
            }
        }
        //for(int i=1;i<=2*n;++i)cout<<c[i].w<<" ";
        //cout<<endl;
        /*for(int i=1;i<=2*n;++i){
            int p=head[i];
            while(p!=0){
                printf("%d %d %d
    ",i,ll[p].goal,ll[p].power);
                p=ll[p].next;
            }
        }*/
        
        for(int i=2;i<=2*n;++i)dis[i]=1147483641;
        dis[1]=0;
        q1.push(1);
        tt[1]=true;
        while(!q1.empty()){
            int k=q1.front(); q1.pop(); tt[k]=false;
            int p=head[k];
            while(p!=0){
                if(dis[ll[p].goal]>dis[k]+ll[p].power){
                    dis[ll[p].goal]=dis[k]+ll[p].power;
                    if(tt[ll[p].goal]==false){
                        tt[ll[p].goal]==true;
                        q1.push(ll[p].goal);
                    }
                }
                p=ll[p].next;
            }
        }
        //for(int i=1;i<=2*n;++i)cout<<dis[i]<<" ";
        printf("%d",min(dis[n],dis[2*n]));
        return 0;
    }

    最后勉励自己:路漫漫其修远兮,吾将上下而求索。

  • 相关阅读:
    Python的词法分析与语法分析
    使用svn log确定分支创建的时间点
    Python的作用域
    SVN的版本日期
    理解SVN关键词BASE,HEAD,COMMITTED,PREV
    SVN的属性
    EL表达式 (详解)
    java jsp el fn
    java防止表单重复提交
    数据库的事务处理
  • 原文地址:https://www.cnblogs.com/cxl681237/p/6377891.html
Copyright © 2020-2023  润新知