【分块】 codeforces 455D - Serega and Fun

分块+双端队列。。。然后两种操作都能在sqrt(n)时间里实现。。。

#include <iostream>  
#include <queue>  
#include <stack>  
#include <map>  
#include <set>  
#include <bitset>  
#include <cstdio>  
#include <algorithm>  
#include <cstring>  
#include <climits>  
#include <cstdlib>
#include <cmath>
#include <time.h>
#define maxn 100005
#define maxm 100005
#define eps 1e-10
#define mod 3
#define INF 1e17
#define lowbit(x) (x&(-x))  
#define ls o<<1
#define rs o<<1 | 1
#define lson o<<1, L, mid  
#define rson o<<1 | 1, mid+1, R  
typedef long long LL;
//typedef int LL;
using namespace std;

deque<int>::iterator it; 
struct node
{
	deque<int> q;
	int num[maxn];
}block[405];
int s, sn, n, m;

void init(void)
{
	int x, b;
	scanf("%d", &n);
	s = pow(n, 0.618);
	if(n % s == 0) sn = n/s;
	else sn = n/s + 1;
	for(int i = 0; i < n; i++) {
		scanf("%d", &x);
		b = i/s;
		block[b].q.push_back(x);
		block[b].num[x]++;
	}
	scanf("%d", &m);
}
void work(void)
{
	int ans = 0;
	int a, b, aa, bb, k, l, r, tmp, x, v;
	while(m--) {
		scanf("%d%d%d", &k, &l, &r);
		l = ((l + ans - 1) % n);
		r = ((r + ans - 1) % n);
		if(l >= r) swap(l, r);
		a = l/s, b = r/s;
		aa = l%s, bb = r%s;
		if(k == 1) {
			if(a == b) {
				it = block[b].q.begin() + bb;
				tmp = *it;
				block[b].q.erase(block[b].q.begin() + bb);
				block[b].q.insert(block[b].q.begin() + aa, tmp);
			}
			else {
				it = block[b].q.begin() + bb;
				tmp = *it;
				block[b].q.erase(block[b].q.begin() + bb);
				block[b].num[tmp]--;
				for(int i = a; i < b; i++) {
					x = block[i].q.back();
					block[i].q.pop_back();
					block[i].num[x]--;
					block[i+1].q.push_front(x);
					block[i+1].num[x]++;
				}
				block[a].q.insert(block[a].q.begin() + aa, tmp);
				block[a].num[tmp]++;
			}
		}
		else {
			scanf("%d", &v);
			v = ((v + ans - 1) % n) + 1;
			ans = 0;
			if(a == b) {
				for(it = block[a].q.begin() + aa; it <= block[a].q.begin() + bb; it++) if(*it == v) ans++;
			}
			else {
				for(int i = a + 1; i < b; i++) ans += block[i].num[v];
				for(it = block[a].q.begin() + aa; it < block[a].q.end(); it++) if(*it == v) ans++;
				for(it = block[b].q.begin(); it <= block[b].q.begin() + bb; it++) if(*it == v) ans++;
			}
			printf("%d\n", ans);
		}
	}
}
int main(void)
{
	init();
	work();
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值