Noip 2013 day 2 被虐报告(+解题报告)

作者: AmadeusChan | 来源:发表于2018-10-03 13:44 被阅读2次

    今年的的Noip确实有些坑,Day2没有数论,而且还比day1容易。。。。。。

    第一题:

    直接模拟,如果h[i]>h[i-1],ans+=h[i]-h[i-1],我白痴的写了离散化+模拟,硬是把复杂度从O(n)搞到了O(n log n)。。。

    第二题:

    动态规划+BIT优化:

    用f(i,0)表示以i为结尾的且最后一段上升的子序列最大长度,f(i,1)表示表示以i为结尾的且最后一段下降的子序列最大长度,那么答案明显就是max{f(i,0),f(i,1)}

    方程:

    f(i,0)=max{f(j,1)}+1 0<=j<i且h[j]<h[i]

    f(i,1)=max{f(j,0)}+1 0<=j<i且h[j]>h[i]

    边界:f(0,0)=f(0,1)=0

    这个方程直接DP复杂度是O(N^2),但是,可以用两个BIT来维护max(f(j,0)),max(f(j,1)),这样复杂度就降到了O(n log n),可以无压力过。

    好像有大神说这道题的f(i)可以直接用f(i-1)推到,所以复杂度仅为O(n),求指点。

    第三题:

    这道题没什么把握,我写的是裸的q次BFS,后来觉得用双向BFS省去一半的搜索量应该可以过吧。。。。大概。。。。。

    突然语文课上想到解法了,发一下:

    首先,进行O(n^4)的预处理,预处理出要移动的棋子在某一位置,空格在其上下左右四个方向上,然后棋子上下左右移动一个的代价,然后每次查询跑最短路即可。

    用Dijstra的话,复杂度:O(n^4+q n^2 log n)

    总而言之,今年还是被NOIP坑的够呛,只能勉强求求不下一等了。。。。555

    代码(都在SMART OJ的非官方数据上过了,应该没啥问题)(详细请见最下方附带的题解文件):

    T1:

    #include <cstdio>
    #define MAXN 100010
    int h[MAXN],ans=0,n;
    int main() {
        h[0]=0;
        scanf("%d",&n);
        for (int i=0;i++<n;) {
            scanf("%d",&h[i]);
            if (h[i]>h[i-1]) ans+=h[i]-h[i-1];
        }
        printf("%d\n",ans);
        return 0;
    }
    

    T2:

    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    #define MAXN 100010
    #define lowbit(x)(((~(x))+1)&x)
    #define MAXH 1000010
    #define For(i,x) for (int i=x;i;i-=lowbit(i))
    #define rep(i,x) for (int i=x;i<=maxh;i+=lowbit(i))
    int t0[MAXH],t1[MAXH];
    int h[MAXN],n,maxh=0;
    int f[MAXN][2],ans=0;
    void Add0(int x,int y) {
        rep(i,x) t0[i]=max(t0[i],y);
    }
    void Add1(int x,int y) {
        rep(i,x) t1[i]=max(t1[i],y);
    }
    int Max0(int x) {
        int rec=0;
        For(i,x) rec=max(rec,t0[i]);
        return rec;
    }
    int Max1(int x) {
        int rec=0;
        For(i,x) rec=max(rec,t1[i]);
        return rec;
    }
    int main() {
        scanf("%d",&n);
        for (int i=0;i++<n;) {
            scanf("%d",&h[i]);
            maxh=max(maxh,++h[i]);
            f[i][0]=f[i][1]=1;
        }
        maxh++;
        memset(t0,0,sizeof(t0)),memset(t1,0,sizeof(t1));
        for (int i=0;i++<n;) {
            f[i][0]=max(Max0(h[i]-1)+1,f[i][0]);
            f[i][1]=max(Max1(maxh-h[i]-1)+1,f[i][1]);
            Add0(h[i],f[i][1]),Add1(maxh-h[i],f[i][0]);
            ans=max(ans,max(f[i][0],f[i][1]));
        }
        printf("%d\n",ans);
        return 0;
    }
    

    T3(最短路):

    #include <iostream>
    
    #include <algorithm>
    
    #include <cstring>
    
    #include <queue>
    
    using namespace std;
    
    #define MAXN 32
    
    #define MAXV 50010
    
    #define inf (1<<26)
    
    const int dir[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
    
    struct edge{
    
            edge *next;
    
            int t,d;
    
            edge (){
    
                  next=NULL;
    
            }
    
    }*head[MAXV];
    
    void AddEdge(int s,int t,int d){
    
            edge *p=new(edge);
    
           p->t=t,p->d=d;
    
           p->next=head[s];
    
            head[s]=p;
    
    }
    
    int Map[MAXN][MAXN],n,m,q,ex,ey,sx,sy,tx,ty,v[MAXN][MAXN][4],V=0,dist[MAXN][MAXN],Move[MAXN][MAXN][4][4],Dist[MAXV];
    
    bool f[MAXV];
    
    int S,T;
    
    struct node{
    
            int x,y;
    
            node (int _x,int _y):x(_x),y(_y){}
    
    };
    
    queue<node>Q;
    
    int Bfs(int Sx,int Sy,int Tx,int Ty){
    
            if(Sx==Tx&&Sy==Ty)return 0;
    
            while(!Q.empty()) Q.pop();
    
            for(int i=0;i++<n;) for(int j=0;j++<m;)dist[i][j]=inf;
    
           dist[Sx][Sy]=0;
    
           Q.push(node(Sx,Sy));
    
            while(!Q.empty()){
    
                   node u=Q.front();
    
                  Q.pop();
    
                   for(int i=0;i<4;i++){
    
                          if(Map[u.x+dir[i][0]][u.y+dir[i][1]]&&dist[u.x+dir[i][0]][u.y+dir[i][1]]==inf){
    
                                   dist[u.x+dir[i][0]][u.y+dir[i][1]]=dist[u.x][u.y]+1;
    
                                   if(u.x+dir[i][0]==Tx&&u.y+dir[i][1]==Ty)return dist[u.x][u.y]+1;
    
                                  Q.push(node(u.x+dir[i][0],u.y+dir[i][1]));
    
                          }
    
                   }
    
            }
    
            return inf;
    
    }
    
    struct Cmp{
    
            bool operator()(int x,int y){
    
                   return Dist[x]>Dist[y];
    
            }
    
    };
    
    priority_queue<int,vector<int>,Cmp>Pq;
    
    int spfa(){
    
            for(int i=0;i++<V;)Dist[i]=inf;
    
            memset(f,true,sizeof(f));
    
            while(!Pq.empty()) Pq.pop();
    
            Dist[S]=0;
    
            Pq.push(S);
    
            while(!Pq.empty()){
    
                   int u=Pq.top();
    
                  Pq.pop();
    
                   if(!f[u])continue;
    
                   f[u]=false;
    
                   if(u==T)return Dist[T];
    
                   for(edge *p=head[u];p;p=p->next){
    
                          if(Dist[p->t]>Dist[u]+p->d){
    
                                  Dist[p->t]=Dist[u]+p->d;
    
                                   f[p->t]=true;
    
                                  Pq.push(p->t);
    
                          }
    
                   }
    
            }
    
            return Dist[T]<inf?Dist[T]:-1;
    
    }
    
    int main(){
    
            cin>>n>>m>>q;
    
            memset(Map,0,sizeof(Map));
    
            for(int i=0;i++<n;){
    
                   for(int j=0;j++<m;){
    
                          cin>>Map[i][j];
    
                          for(int k=0;k<4;k++){
    
                                   v[i][j][k]=++V;
    
                          }
    
                   }
    
            }
    
            for(int i=0;i++<n;){
    
                   for(int j=0;j++<m;){
    
                          for(int k=0;k<4;k++){
    
                                   for(int h=0;h<4;h++)Move[i][j][k][h]=inf;
    
                          }
    
                   }
    
            }
    
            for(int i=0;i++<n;){
    
                   for(int j=0;j++<m;){
    
                          if(Map[i][j]){
    
                                   Map[i][j]=0;
    
                                   for(int k=0;k<4;k++){
    
                                          if(Map[i+dir[k][0]][j+dir[k][1]]){
    
                                                  for(int h=0;h<4;h++){
    
                                                        if(Map[i+dir[h][0]][j+dir[h][1]]){
    
                                                               Move[i][j][k][h]=Bfs(i+dir[k][0],j+dir[k][1],i+dir[h][0],j+dir[h][1])+1;
    
                                                        }
    
                                                  }
    
                                          }
    
                                   }
    
                                   Map[i][j]=1;
    
                          }
    
                   }
    
            }
    
            memset(head,0,sizeof(head));
    
            for(int i=0;i++<n;) for(int j=0;j++<m;) for(int k=0;k<4;k++)for(int h=0;h<4;h++)
    
                                          if(Move[i][j][k][h]<inf)AddEdge(v[i][j][k],v[i+dir[h][0]][j+dir[h][1]][h^1],Move[i][j][k][h]);
    
            while(q--){
    
                   cin>>ex>>ey>>sx>>sy>>tx>>ty;
    
                   if(sx==tx&&sy==ty){ cout<<0<<endl;continue;}
    
                  S=++V; T=++V;
    
                   if(Map[sx][sy]==0||Map[tx][ty]==0){cout<<-1<<endl; continue; }
    
                  Map[sx][sy]=0;
    
                   for(int i=0;i<4;i++){
    
                          if(Map[sx+dir[i][0]][sy+dir[i][1]]){
    
                                   int D=Bfs(ex,ey,sx+dir[i][0],sy+dir[i][1]);
    
                                   if(D<inf)AddEdge(S,v[sx][sy][i],D);
    
                          }
    
                   }
    
                  Map[sx][sy]=1;
    
                   for(int i=0;i<4;i++) if(Map[tx+dir[i][0]][ty+dir[i][1]])AddEdge(v[tx][ty][i],T,0);
    
                   cout<<spfa()<<endl;
    
            }
    
            return 0;
    
    }
    
    
    

    附:将Noip的思路整理了一下,顺便将题解和代码一起发了上来

    (度娘盘网址:http://pan.baidu.com/s/1osWXY

    相关文章

      网友评论

        本文标题:Noip 2013 day 2 被虐报告(+解题报告)

        本文链接:https://www.haomeiwen.com/subject/sdbzoftx.html