<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      P12704 Retribution

      P12704 Retribution

      我也不知道為什么能過做法。

      考慮暴力縮點,然后做線段樹合并。

      細節上,由于要在可持久化線段樹上合并,所以每次要新開節點,在合并的時候多剪枝減少棧調用和新開節點。
      如果嘗試將詢問離線掛在每個 SCC 上的話,\(10^6\) 的無序 vector 應該還不如存新節點。

      如果亂開東西大概率空間會炸。
      一共有 \(10^6\) 個 SCC,注意到線段樹上實際有非常多節點都連向同一個節點每次新建的點并不會很多。
      實際精細計算一下空間只要 \(9\times 10^7\) 個 int 就行。千萬不要亂開 vector。

      留下不到一百兆給棧調用和臨時的隊列啥的應該是差不多夠了,事實上對于數據是剛剛好。

      代碼

      const int N = 1510,LG = 21;
      int n,m,q,seed;
      char s[N][N];
      int dx[4] = {-1,+1,+0,+0};
      int dy[4] = {+0,+0,-1,+1};
      inline int id(int x,int y){
      	return m*(x-1)+y;
      }
      struct{
      	int to,nex;
      }edge[N*N*3];
      int head[N*N],edge_num,ind[N*N];
      inline void add(int x,int y){
      	edge[++edge_num].to = y;
      	edge[edge_num].nex = head[x];
      	head[x] = edge_num;
      }
      int dfn[N*N],low[N*N],st[N*N],id_scc[N*N],dtop,stop,col_cnt;
      inline void tarjan(int now){
      	dfn[now] = low[now] = ++dtop;
      	st[++stop] = now;
      	for(int i=head[now];i;i=edge[i].nex){
      		int tto = edge[i].to;
      		if(!dfn[tto]){
      			tarjan(tto);
      			low[now] = Min(low[tto],low[now]);
      		}
      		else if(!id_scc[tto]) low[now] = Min(low[now],dfn[tto]);
      	}
      	if(low[now]==dfn[now]){
      		++col_cnt;
      		while(st[stop]^now){
      			id_scc[st[stop]] = col_cnt;
      			--stop;
      		}
      		id_scc[st[stop]] = col_cnt;
      		--stop;
      	}
      	head[now] = 0;
      }
      struct node{
      	int ls,rs;
      }tr[N*N*LG];
      int rt[N*N],cnt;
      inline int merge(int u,int v,int nl,int nr){
      	if(!u || !v) return u|v;
      	if(u==v) return u;
      	int p = ++cnt;
          if(nl==nr){
      		tr[p].ls = tr[u].ls | tr[v].ls;
              return p;
          }
          int mid = (nl+nr) >> 1;
          tr[p].ls = merge(tr[u].ls,tr[v].ls,nl,mid);
          tr[p].rs = merge(tr[u].rs,tr[v].rs,mid+1,nr);
          return p;
      }
      inline void insert(int &p,int nl,int nr,int x){
      	if(!p) p  = ++cnt;
      	int mid = (nl+nr) >> 1;
      	if(nl==nr){
      		tr[p].ls = 1;
      		return ;
      	}
      	if(x<=mid) insert(tr[p].ls,nl,mid,x);
      	else insert(tr[p].rs,mid+1,nr,x);
      }
      inline int query(int p,int nl,int nr,int x){
      	if(!p) return 0;
      	int mid = (nl+nr) >> 1;
      	if(nl==nr) return tr[p].ls;
      	if(x<=mid) return query(tr[p].ls,nl,mid,x);
      	else return query(tr[p].rs,mid+1,nr,x);
      }
      inline void topo(){
      	queue <int> q;
      	for(int i=1;i<=col_cnt;++i){
      		insert(rt[i],1,col_cnt,i);
      		if(!ind[i]) q.push(i);
      	}
      	while(!q.empty()){
      		int now = q.front();
      		q.pop();
      		for(int i=head[now];i;i=edge[i].nex){
      			int tto = edge[i].to;
      			rt[tto] = merge(rt[tto],rt[now],1,col_cnt);
      			--ind[tto];
      			if(!ind[tto]) q.push(tto);
      		}
      	}
      }
      int main(){
      	// freopen("in.in","r",stdin);
          // freopen("out.out","w",stdout);
      
      	read(n,m,q,seed);
      	init(seed);
      	for(int i=1;i<=n;++i){
      		scanf("%s",s[i]+1);
      		for(int j=1;j<=m;++j){
      			for(int t=0;t<4;++t){
      				if(s[i][j]=='U' && t==0) continue;
      				if(s[i][j]=='D' && t==1) continue;
      				if(s[i][j]=='L' && t==2) continue;
      				if(s[i][j]=='R' && t==3) continue;
      				int tx = i+dx[t];
      				int ty = j+dy[t];
      				if(tx<1 || tx>n || ty<1 || ty>m) continue;
      				add(id(i,j),id(tx,ty));
      			}
      		}
      	}
      	for(int i=1;i<=n;++i){
      		for(int j=1;j<=m;++j){
      			if(!dfn[id(i,j)]) tarjan(id(i,j));
      		}
      	}
      	edge_num = 0;
      	for(int i=1;i<=n;++i){ 
      		for(int j=1;j<=m;++j){
      			for(int t=0;t<4;++t){
      				if(s[i][j]=='U' && t==0) continue;
      				if(s[i][j]=='D' && t==1) continue;
      				if(s[i][j]=='L' && t==2) continue;
      				if(s[i][j]=='R' && t==3) continue;
      				int tx = i+dx[t];
      				int ty = j+dy[t];
      				if(tx<1 || tx>n || ty<1 || ty>m) continue;
      				if(id_scc[id(i,j)]^id_scc[id(tx,ty)]){
      					add(id_scc[id(tx,ty)],id_scc[id(i,j)]);
      					++ind[id_scc[id(i,j)]];
      				}
      			}
      		}
      	}
      	topo();
      	for(int i=1,a,b,x,y;i<=q;++i){
      		a = get(1,n); b = get(1,m); x = get(1,n); y = get(1,m);
      		query(rt[id_scc[id(a,b)]],1,col_cnt,id_scc[id(x,y)]) ? putchar('1') : putchar('0');
      	}
      
      	// fclose(stdin);
      	// fclose(stdout);
      	return 0;
      }
      

      后話

      機房里大家都覺得這種東西非常假(我也覺得很假,但是就是寫了然后過了),但實測這玩意跑得飛快。

      我們在做合并的時候,只要發現處于同一個點就可以直接退出。而題里給出的圖,會使得有非常多的線段樹共用了同一個節點,合并復雜度事實上非常跑不滿。

      根據我本人精心構造的數據以及對數據點的判斷,線段樹新開的節點實際非常少大概在 \(O(n^2\log{n^2})\),合并次數大概在 \(O(n\log^2n)\) 級別。這是綽綽有余的。

      posted @ 2025-10-01 11:52  Tmbcan  閱讀(10)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 成人看的污污超级黄网站免费| 亚洲码亚洲码天堂码三区| 亚洲第一香蕉视频啪啪爽| 亚洲精品一区二区制服| 亚欧美闷骚院| 国产嫩草精品网亚洲av| 亚洲国产成人无码电影| 北岛玲中文字幕人妻系列| 四虎影视一区二区精品 | 伦伦影院午夜理论片| 国产精品免费看久久久| 日本三级成本人网站| 99久久婷婷国产综合精品青草漫画| 91精品国产免费人成网站| 一本精品中文字幕在线| 人妻丰满熟妇av无码区不卡| 蜜臀av入口一区二区三区| 国产精品成人高潮av| 欧美成人午夜在线观看视频| 亚洲国产一区二区av| 欧产日产国产精品精品| 国内视频偷拍久久伊人网| 日韩欧美亚洲综合久久| 国产成人午夜在线视频极速观看| 亚洲综合伊人五月天中文| 毛片无码免费无码播放| 国产成人一区二区三区视频免费 | 老色鬼在线精品视频在线观看| 国产精品色内内在线播放| 四虎永久免费高清视频| 国产精品推荐视频一区二区| 亚洲国产色婷婷久久99精品91| 久久久精品2019中文字幕之3| 超碰成人人人做人人爽| 色婷婷综合久久久久中文一区二区| 野花韩国高清电影| 亚洲综合色区另类av| 日本道高清一区二区三区| 亚洲av免费看一区二区| 久久99九九精品久久久久蜜桃 | 日本无产久久99精品久久|