【Codeforces455D】Seregaand Fun | Block、Deque

トピックリンク:質問リンク

本旨:

NNの長さを与えるNシーケンスでは、次の2つの操作がこのシーケンスで実行されます。

  • 1、l、r:1、l、r: 1 l r間隔[l、r] [l、r][ l r ]内側のループが1か所移動します
  • 2、l、r、k:2、l、r、k: 2 l r kクエリ間隔内[l、r] [l、r][ l R ]における桁数KKk、必須のオンライン。

質問のアイデア:

チャンク化を検討し、シーケンスをsqrt(n)sqrt(n)に分割します。s q r t n ブロック、各ブロックは双方向キューを維持します。

間隔の変更操作の場合:中央のブロックはO 1O1を直接渡すことができますO 1の動作が完了し、両側のブロックが判定されます。

間隔のクエリ操作の場合:ルートブロックの数のタイプを維持し、この計算を完全なブロックに対して直接使用し、不完全なブロックを直接判断します。

複雑さ:O(m ∗ sqrt(n)∗ 2)O(m * sqrt(n)* 2)O ms q r t n 2

コード:

/*** keep hungry and calm CoolGuang!  ***/
#pragma GCC optimize(3)
#include <bits/stdc++.h>
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define dl(x) printf("%lld\n",x);
#define di(x) printf("%d\n",x);
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
const ll INF= 1e18+7;
const ll maxn = 1e5+700;
const ll mod= 100003;
const double eps = 1e-9;
const double PI = acos(-1);
template<typename T>inline void read(T &a){
    
    char c=getchar();T x=0,f=1;while(!isdigit(c)){
    
    if(c=='-')f=-1;c=getchar();}
while(isdigit(c)){
    
    x=(x<<1)+(x<<3)+c-'0';c=getchar();}a=f*x;}
ll n,m,p;
int c[350][maxn];
deque<int>q[350];
int L[maxn],R[maxn];
int b[maxn];
int num[maxn];
int block = 0;
int save[maxn];
void Modify(int l,int r){
    
    
	if(l>r) swap(l,r);
	int s = b[l],t = b[r];
	int cnt = 0;
	if(s == t){
    
    
		while(!q[s].empty()) save[++cnt] = q[s].back(),q[s].pop_back();
		l-= (s-1)*block,r-=(s-1)*block;
		int temp = save[r];
		for(int i=r;i>=l+1;i--) save[i] = save[i-1];
		save[l] = temp;
		for(int i=1;i<=cnt;i++) q[s].push_front(save[i]);
		return;
	}
	///t>s
	int last = q[s].front();
	for(int i=s+1;i<=t-1;i++){
    
    
		q[i].push_back(last);
		c[i][last]++;
		last = q[i].front();
		q[i].pop_front();
		c[i][last]--;
	}
	cnt = 0;
	///t块单独
	for(int i=(t-1)*block+1;i<=r;i++) c[t][q[t].back()]--,save[++cnt] = q[t].back(),q[t].pop_back();
	for(int i=cnt-1;i>=1;i--)c[t][save[i]]++,q[t].push_back(save[i]);
	q[t].push_back(last),c[t][last]++;
	last = save[cnt];
	cnt = 0;
	///s块单独
	for(int i=l;i<=R[s];i++) c[s][q[s].front()]--,save[++cnt] = q[s].front(),q[s].pop_front();
	q[s].push_front(last),c[s][last]++;
	for(int i=cnt;i>=2;i--) c[s][save[i]]++,q[s].push_front(save[i]);
}
ll Query(int k,int l,int r){
    
    
	if(l>r) swap(l,r);
	int s = b[l],t = b[r];
	int cnt = 0;
	int ans = 0;
	if(s == t){
    
    
		while(!q[s].empty()) save[++cnt] = q[s].back(),q[s].pop_back();
		l-= (s-1)*block,r-=(s-1)*block;
		for(int i=l;i<=r;i++) if(save[i] == k) ans++;
		for(int i=1;i<=cnt;i++) q[s].push_front(save[i]);
		return ans;
	}
	for(int i=s+1;i<=t-1;i++) ans += c[i][k];
	cnt = 0;
	///t块单独
	for(int i=(t-1)*block+1;i<=r;i++) ans += ((q[t].back() == k)?1:0),save[++cnt] = q[t].back(),q[t].pop_back();
	for(int i=cnt;i>=1;i--) q[t].push_back(save[i]);
	cnt = 0;
	///s块单独
	for(int i=l;i<=R[s];i++) ans += ((q[s].front() == k)?1:0),save[++cnt] = q[s].front(),q[s].pop_front();
	for(int i=cnt;i>=1;i--) q[s].push_front(save[i]);
	return ans;
}
int main(){
    
    

	/*q[1].push_front(2);
	q[1].push_front(3);
	q[1].push_back(1);
	debug(q[1].back());*/
	read(n);
	block = sqrt(n);
	for(int i=1;i<=n;i++) read(num[i]);
	for(int i=1;i<=n;i++){
    
    
		b[i] = (i-1)/block + 1;
		c[b[i]][num[i]]++;
		L[i] = (i%block == 1)?1:0;
		R[b[i]] = min(b[i]*block*1ll,n);
		q[b[i]].push_front(num[i]);
	}
	int lastans = 0;
	read(m);
	for(int i=1;i<=m;i++){
    
    
		int op,x,y,z;
		read(op);read(x);read(y);
		x = (x+lastans-1)%n + 1;
		y = (y+lastans-1)%n + 1;
		if(op == 1) Modify(x,y);
		else{
    
    
			read(z);
			z = (z+lastans-1)%n+1;
			lastans = Query(z,x,y);
			di(lastans);
		}
	}
    return 0;

}
/***
7
6 6 2 7 4 2 5
7
1 3 6
2 1 2 2
***/

おすすめ

転載: blog.csdn.net/qq_43857314/article/details/113101466