zoukankan      html  css  js  c++  java
  • [JOI2012春季合宿]Rotate (链表)

    题意

    题解

    又是一道神仙题……
    显然的做法是大力splay,时间复杂度(O((N+Q)Nlog N)), 可以卡掉。
    正解: 使用十字链表维护矩阵,在周围增加第(0)行/列和第((n+1))行/列,设(li[x][d])表示(x)这个点在(d)这个方向上的下一个元素的编号是什么(一开始给每个元素都编上号)。那么对于一次旋转,子矩形边界上的格子暴力修改,内部相当于把(4)个方向做了个轮换,因此可以打标记实现。
    然而本题的实现方法比较神奇: 每次修改从((0,0))走到((x,y)) (只花费(O(N))的时间),首先((0,0))的标记一定是正确的(因为没有修改过),然后一路上通过当前点和下一个点互相储存位置的偏移量以及当前点的正确标记确定下一个点的正确标记。(详见代码,我的代码里标记的含义是实际方向等于存储方向加标记)
    时间复杂度(O((N+Q)N)).

    代码

    #include<bits/stdc++.h>
    #define llong long long
    using namespace std;
     
    const int N = 1002;
    const int dx[4]={1,0,-1,0},dy[4]={0,1,0,-1};
    char ch[N+3];
    char a[N*N+3];
    int li[N*N+3][4];
    int tag[N*N+3];
    int aux1[4][N+3],aux2[4][N+3];
    int n,q;
     
    int getid(int x,int y) {return x*(n+2)+y+1;}
    int getnxt(int u,int dir)
    {
        int ret = li[u][(dir-tag[u]+4)&3];
        for(int i=0; i<4; i++) {if(li[ret][i]==u) {tag[ret] = (dir-i+6)&3;}}
        return ret;
    }
     
    int main()
    {
        scanf("%d%d",&n,&q);
        for(int i=1; i<=n; i++) {scanf("%s",ch+1); for(int j=1; j<=n; j++) a[getid(i,j)] = ch[j];}
        for(int i=0; i<=n+1; i++)
        {
            for(int j=0; j<=n+1; j++)
            {
                int u = getid(i,j);
                for(int k=0; k<4; k++)
                {
                    if(i+dx[k]>=0&&i+dx[k]<=n+1&&j+dy[k]>=0&&j+dy[k]<=n+1) {li[u][k] = getid(i+dx[k],j+dy[k]);}
                }
            }
        }
        while(q--)
        {
            int x,y,l; scanf("%d%d%d",&x,&y,&l);
            int u = 1;
            for(int i=0; i<x; i++) u = getnxt(u,0);
            for(int i=0; i<y; i++) u = getnxt(u,1);
            for(int k=0; k<4; k++)
            {
                for(int i=0; i<l; i++)
                {
                    aux1[k][i] = u; aux2[k][i] = getnxt(u,(k+3)&3);
                    if(i<l-1) u = getnxt(u,k);
                }
            }
            for(int k=0; k<4; k++)
            {
                for(int i=0; i<l; i++)
                {
                    li[aux1[k][i]][(k-tag[aux1[k][i]]+3)&3] = aux2[(k+1)&3][i];
                    li[aux2[k][i]][(k-tag[aux2[k][i]]+5)&3] = aux1[(k+3)&3][i];
                }
            }
        }
        int u = 1;
        for(int i=1; i<=n; i++)
        {
            u = getnxt(u,0);
            int uu = u;
            for(int j=1; j<=n; j++) {uu = getnxt(uu,1); ch[j] = a[uu];/* printf("%d ",uu);*/}
            puts(ch+1);
    //      puts("");
        }
        return 0;
    }
    
  • 相关阅读:
    微软外服 AlI In One
    js 循环多次和循环一次的时间的性能对比 All In One
    vue inject All In One
    Excel 表格数据倒置 All In One
    SVG tickets All In One
    OH MY ZSH All In One
    js array for loop performance compare All In One
    mac terminal show You have new mail All In one
    新闻视频 26 制作母版页
    转自牛腩 母版页和相对路径
  • 原文地址:https://www.cnblogs.com/suncongbo/p/11723879.html
Copyright © 2011-2022 走看看