zoukankan      html  css  js  c++  java
  • Gym101620D Donut Drone

    Link
    我们知道每走一步一定会往前走一列。
    考虑求出(next_i)表示从((i,1))开始走,下一次走到第一列的时候在第几行。
    可以先预处理(a_{i,j}=[l,r])表示(forall kin[l,r]),从((k,1))开始走,会走到((i,j)),不难发现这一定是个区间。
    (O(rc))地预处理(a)后,就可以(O(r))地计算(next)了。
    对于修改((x,y,v)),第(y)列中(a)发生变动的点的一定在([x-2,x+2])行。
    那么我们可以对于这(5)个点,暴力往后修改(a),单次复杂度为(O(c))
    对于询问,考虑(x ightarrow next_x)会构成一棵内向基环树。
    我们先计算完整地走完了多少次所有列,再计算这样会在基环树上到达哪个点,然后再暴力往后走即可,单次复杂度为(O(r+c))
    总的时间复杂度为(O(rc+q(r+c)))

    #include<cstdio>
    #include<cctype>
    #include<cstring>
    #include<utility>
    #define fi first
    #define se second
    using pi=std::pair<int,int>;
    const int N=2007;
    int r,c,next[N],val[N][N],num[N];pi a[N][N];
    char get(){char c=getchar();while(!islower(c))c=getchar();return c;}
    int read(){int x=0,c=getchar();while(!isdigit(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
    int pre(int x){return x==1? r:x-1;}
    pi merge(pi p,pi q){return ~p.fi? (~q.fi? (p.se%r+1==q.fi? pi{p.fi,q.se}:pi{q.fi,p.se}):p):q;}
    int go(int x,int y)
    {
        y=y%c+1;int mx=0,id=0;
        for(int i=0,p=pre(x);i<3;++i,p=p%r+1) if(mx<val[p][y]) mx=val[id=p][y];
        return id;
    }
    void cal(int x,int y)
    {
        if(y==1) return a[x][y]={x,x},void();
        a[x][y]={-1,-1};
        for(int i=0,p=pre(x);i<3;++i,p=p%r+1) if(go(p,y-1)==x) a[x][y]=merge(a[x][y],a[p][y-1]);
    }
    void build()
    {
        for(int i=1,t;i<=r;++i)
        {
    	if(!~a[i][c].fi) continue;
    	next[a[i][c].fi]=t=go(i,c);
    	for(int j=a[i][c].fi%r+1;j!=a[i][c].se%r+1;j=j%r+1) next[j]=t;
        }
    }
    void rebuild(int x,int y){for(;y^1;x=go(x,y),y=y%c+1)cal(x,y);}
    int main()
    {
        r=read(),c=read();
        for(int i=1;i<=r;++i) for(int j=1;j<=c;++j) val[i][j]=read();
        for(int j=1;j<=c;++j) for(int i=1;i<=r;++i) cal(i,j);
        build();
        for(int Q=read(),x=1,y=1;Q;--Q)
    	if(get()=='m')
    	{
    	    int k=read(),now=1;memset(num,0,sizeof num);
    	    while(k&&y^1) x=go(x,y),y=y%c+1,--k;
    	    while(k>=c&&!num[x]) num[x]=now++,x=next[x],k-=c;
    	    for(k%=(now-num[x])*c;k>=c;) k-=c,x=next[x];
    	    while(k--) x=go(x,y++);
    	    printf("%d %d
    ",x,y);
    	}
    	else
    	{
    	    int x=read(),y=read(),v=read();val[x][y]=v;
    	    for(int i=0,p=pre(pre(x));i<5;++i,p=p%r+1) rebuild(p,y);
    	    build();
    	}
    }
    
  • 相关阅读:
    两数之和
    IDEA类的旁边有个对勾
    Markdown 常用语法
    GitLab 使用指南(IntelliJ IDEA)
    Python yield 用法
    Mac for MySQL 5.7 安装教程
    Mac Hadoop2.6(CDH5.9.2)伪分布式集群安装
    Hive 建外链表到 Hbase(分内部表、外部表两种方式)
    hive grouping sets 等聚合函数
    hive row_number等窗口分析函数
  • 原文地址:https://www.cnblogs.com/cjoierShiina-Mashiro/p/12594569.html
Copyright © 2011-2022 走看看