2021-08-12 SSL 模拟赛 T3【分块】

2021-08-12 SSL 模拟赛 T3

没有标题的第 n > = ( 1 0 9   m o d   20 ) n>=(10^9 \bmod 20) n>=(109mod20)
在这里插入图片描述

思路:

分块,我太菜了,这里转载大佬的思路:
在这里插入图片描述
码量巨大
全 ! 全! 体 ! 体! 起 ! 起! 立 ! 立!

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<deque>
#include<cstring>
#include<cmath>
#define r register
#define rep(i,x,y) for(r ll i=x;i<=y;++i)
#define per(i,x,y) for(r ll i=x;i>=y;--i)
using namespace std;
typedef long long ll;
const ll V=1e5+10,N=360;
ll n,m,a[V],f[N][V],cnt,vis[V],c[V],d[V];
ll s,x,y,k,v;
deque<ll> q[N];
char buf[1<<23], *p1=buf, *p2=buf, obuf[1<<23], *O=obuf;
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1<<21, stdin), p1 == p2) ? EOF : *p1++)
void inline read(ll &x) 
{
    x = 0; char s = getchar();
    while (s < '0' || s > '9') s = getchar();
    while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
}
void put(ll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) put(x/10);
	putchar(x%10+48);
}
void change(ll x,ll y)
{
	if(vis[x]==vis[y])
	{
		ll now=vis[x];
		x%=v,y%=v;
		if(x==0) x=v;
		if(y==0) y=v;
		rep(i,1,x-1)
		 c[i]=q[now].front(),q[now].pop_front();
		rep(i,1,v-y)
		 d[i]=q[now].back(),q[now].pop_back();
		ll x=q[now].back();
		q[now].pop_back() ,q[now].push_front(x);
		per(i,x-1,1) q[now].push_front(c[i]);
		rep(i,1,v-y) q[now].push_back(d[v-i-y+1]);  	
	}
	else
	{
		ll k=vis[x],t=x;
		while(vis[t+1]==k) ++t;
		ll len1=t-x+1;
		rep(i,1,len1)
		{
			c[len1-i+1]=q[k].back();
			q[k].pop_back();
			--f[k][c[len1-i+1]];
		}
		ll p=vis[y],h=y;
		while(vis[h-1]==p) --h;
		ll len2=y-h+1;
		rep(i,1,len2)
		{
			d[i]=q[p].front();
			q[p].pop_front() ;
			--f[p][d[i]];
		}
		q[k].push_back(d[len2]);
		++f[k][d[len2]] ;
		rep(i,1,len1-1)
		{
			q[k].push_back(c[i]) ;
			++f[k][c[i]];
		}
		per(i,len2-1,1)
		{
			q[p].push_front(d[i]);
			++f[p][d[i]]; 
		}
		ll val=q[p-1].back() ;
		if(p==k+1) val=c[len1];
		q[p].push_front(val),f[p][val]++;
		ll ed=c[len1];
		rep(i,k+1,p-1)
		{
			q[i].push_front(ed);++f[i][ed];
			ed=q[i].back();
			q[i].pop_back();
			--f[i][ed];
		}
	}
}
ll ask(ll x,ll y,ll k)
{
	ll res=0;
	if(vis[x]==vis[y]) 
	{
		ll now=vis[x];
		x%=v,y%=v;
		if(x==0) x=v;
		if(y==0) y=v;
		rep(i,1,x-1) //统计不在区间内的合法 k 
		{
			c[i]=q[now].front();
			q[now].pop_front();
		}
		rep(i,1,v-y)
		{
			d[i]=q[now].back();
			q[now].pop_back();
		}
		per(i,x-1,1)
		{
			if(c[i]==k) ++res;
			q[now].push_front(c[i]); 
		}
		rep(i,1,v-y)
		{
			if(d[v-y-i+1]==k) ++res;
			q[now].push_back(d[v-y-i+1]); 
		}
		res=f[now][k]-res;
	}
	else
	{
		ll t=vis[x],u=x;
		while(vis[u+1]==t) ++u;
		ll len1=u-x+1;
		rep(i,1,len1)
		{
			c[len1-i+1]=q[t].back() ;
			q[t].pop_back();
		}
		ll p=vis[y],h=y;
		while(vis[h-1]==p) --h;
		ll len2=y-h+1;
		rep(i,1,len2)
		{
			d[i]=q[p].front();
			q[p].pop_front() ;
		}
		rep(i,1,len1)
		{
			if(c[i]==k) ++res;
			q[t].push_back(c[i]); 
		}
		per(i,len2,1)
		{
			if(d[i]==k) ++res;
			q[p].push_front(d[i]); 
		}
		rep(i,t+1,p-1) res+=f[i][k];
	}
	return res;
}
int main()
{
	scanf("%lld%lld",&n,&m);
	v=sqrt(n);
	rep(i,1,n)
	{
		read(a[i]);
		if(i>cnt*v) ++cnt;
		q[cnt].push_back(a[i]);
		vis[i]=cnt,++f[cnt][a[i]];
	}
	rep(i,1,m)
	{
		read(s),read(x),read(y);
		if(s==1) change(x,y);
		else
		{
			read(k);
			put(ask(x,y,k));
			putchar(10);
		}
	}
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值