终于结尾了.
诶?我定义的常量变成yuzu了?我不要可怜了?
可怜有剧毒!我再用可怜我要爆零了.
好吧其实是因为我研究了橘学.这里我推荐一下Citrus.
支持插入一个数,询问一个位置上的数是多少.
/*
每块开一个vector,插入的时候先询问x指向的块和位置,然后插入就可以了;
询问的时候从第一个vector开始按顺序减去每一块的元素的个数,返回一个pair,first表示所在块,second表示块内的位置.
不要忘记如果某一块插入了很多数字要把所有块推倒重构.
快读快写把我坑死了.
*/
#include //Ithea Myse Valgulious
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
re0 x=0,f=1;rec c=gc();
for (;!isdigit(c);c=gc()) ;//f^=c=='-';
for (;isdigit(c);c=gc()) x=x*10+c-'0';
return x;//*(f?1:-1);
}
inline void read(rel &x){
x=0;re0 f=1;rec c=gc();
for (;!isdigit(c);c=gc()) ;//f^=c=='-';
for (;isdigit(c);c=gc()) x=x*10+c-'0';
x*=f?1:-1;
}
template <typename mitsuha>
inline int write(mitsuha x){
if (!x) return pc(48);
//if (x<0) x=-x,pc('-');
re0 bit[20],i,p=0;
for (;x;x/=10) bit[++p]=x%10;
for (i=p;i;--i) pc(bit[i]+48);
}
}using namespace chtholly;
using namespace std;
#define bl(x) (((x)-1)/block+1)//Which block x belong
#define ls(x) (((x)-1)*block+1)//The left side of block x
#define rs(x) (min(n,(x)*block))//The right side of block x
typedef pair<int,int> pii;
const int yuzu=2e5;
typedef int fuko[yuzu|10];
vector<int> v[yuzu|10];
int n,block,num,top;
fuko a,tmp;
void buildblock()
{
re0 i;
block=sqrt(n),num=n/block+(n%block?1:0);
for (i=1;i<=n;++i) v[bl(i)].push_back(a[i]);
}
pii query(int x)
{
int now=1;
for (;x>v[now].size();) x-=v[now++].size();
return pii(now,x-1);
}
void push_down()//推倒重来
{
top=0;re0 i;
for (i=1;i<=num;v[i++].clear())
for (int j:v[i]) tmp[++top]=j;
int newblock=sqrt(top);num=top/newblock+(top%newblock?1:0);
for (i=1;i<=top;++i) v[bl(i)].push_back(tmp[i]);
}
void insert(int pos,int x)
{
pii now=query(pos);
v[now.first].insert(v[now.first].begin()+now.second,x);
if (v[now.first].size()>20*block) push_down();
}
int main()
{
re0 i;
scanf("%d",&n);
for (i=1;i<=n;++i) scanf("%d",&a[i]);
buildblock();
for (i=1;i<=n;++i)
{
re0 op,l,r,c;
scanf("%d%d%d%d",&op,&l,&r,&c);
if (op)
{
pii ans=query(r);
printf("%d\n",v[ans.first][ans.second]);
}
else insert(l,r);
}
}
区间查询等于c的数的个数,并同时将区间内的所有数改为c.
本题玄学就在于查询的同时进行了修改.
如果查询与修改分开,这题分块就过不了了.
/*
我们来看均摊的复杂度.
对于查询和修改,被修改成同一个数字的可以打上标记.
这样被修改的只有头尾两块.
如果你想让一次查询是O(n)的,必须要先用O(sqrt(n))的复杂度的修改去修改每一块,把所有的标记都破坏掉.
所以复杂度是O(sqrt(n))的.
但是如果查询和修改是分开的,每次只修改一个块内的数,然后查询[1,n],就炸了.
当然这题还是有非常多细节要注意的.
当被打上标记的块被l或者r断开了,必须要把标记下推.
我debug了好久,最后竟然A掉了.
*/
#pragma GCC optimize("inline,Ofast",3)
#include //Ithea Myse Valgulious
#define yuri puts("niconiconi")
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
re0 x=0,f=1;rec c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=x*10+c-'0';
return x*(f?1:-1);
}
inline void read(rel &x){
x=0;re0 f=1;rec c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=x*10+c-'0';
x*=f?1:-1;
}
template <typename mitsuha>
inline int write(mitsuha x){
if (!x) return pc(48);
if (x<0) x=-x,pc('-');
re0 bit[20],i,p=0;
for (;x;x/=10) bit[++p]=x%10;
for (i=p;i;--i) pc(bit[i]+48);
}
}using namespace chtholly;
using namespace std;
#define bl(x) (((x)-1)/block+1)
#define ls(x) (((x)-1)*block+1)
#define rs(x) (min(n,(x)*block))
const int yuzu=1e5;
typedef int fuko[yuzu|10];
fuko a,tag;int n,block,num;
void buildblock()//³õʼ»¯block
{
re0 i;
block=sqrt(n),num=n/block+(n%block?1:0);
}
void debug()
{
re0 i;
for (i=1;i<=n;++i) printf("%d ",a[i]);pl;
for (i=1;i<=num;++i) printf("%d ",tag[i]);pl;
}
void push_down(int x)//标记下推(就是线段树的延迟标记),其实就是暴力修改,然后把标记清零.
{
if (tag[x])
for (re0 i=ls(x);i<=rs(x);++i) a[i]=tag[x];
}
int query(int l,int r,int c)
{
re0 i,ans=0;
push_down(bl(l));
for (i=l;i<=min(r,rs(bl(l)));++i)
ans+=a[i]==c;//暴力
if (bl(r)!=bl(l))//暴力
{
push_down(bl(r));
for (i=ls(bl(r));i<=r;++i) ans+=a[i]==c;
}
for (i=bl(l)+1;iif (!tag[i]) //没有标记,暴力
for (re0 j=ls(i);j<=rs(i);++j) ans+=a[j]==c;
else
ans+=tag[i]==c?rs(i)-ls(i)+1:0;//有标记,O(1)回答.
}
return ans;
}
void update(int l,int r,int c)
{
re0 i;
push_down(bl(l));
for (i=l;i<=min(r,rs(bl(l)));++i)
a[i]=c;//暴力
tag[bl(l)]=0;
if (bl(r)!=bl(l))
{
push_down(bl(r));
for (i=ls(bl(r));i<=r;++i) a[i]=c;//暴力
tag[bl(r)]=0;
}
for (i=bl(l)+1;i//打标记
tag[i]=c;
}
int main()
{
int i;
scanf("%d",&n);
for (i=1;i<=n;++i) scanf("%d",&a[i]);
buildblock();
for (i=1;i<=n;++i)
{
re0 l,r,c;
scanf("%d%d%d",&l,&r,&c);
printf("%d\n",query(l,r,c));
update(l,r,c);
//debug();
}
}
询问区间最小众数.
这题只有询问,看似简单,实则也不简单.
洛谷上有p4168蒲公英,双倍经验了解一下.
以下不是分块9的代码,是蒲公英的.
lojAC代码里可以看到我的.
/*
我们先把这些数离散化一下,然后预处理.
预处理要处理两个玩意.
第一个是[l,r]内有多少个数x.
第二个是块[l,r]内的众数是多少.
第一个O(n),第二个O(n*sqrt(n)).
询问的时候先把ans处理成[belong(l)+1,belong(r)-1]块内的众数.
然后把l,r所在的部分遍历一下,与答案比较.
*/
#include //Ithea Myse Valgulious
#define yuri puts("niconiconi")
namespace chtholly{
typedef long long ll;
#define re0 register int
#define rec register char
#define rel register ll
#define gc getchar
#define pc putchar
#define p32 pc(' ')
#define pl puts("")
/*By Citrus*/
inline int read(){
re0 x=0,f=1;rec c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=x*10+c-'0';
return x*(f?1:-1);
}
inline void read(rel &x){
x=0;re0 f=1;rec c=gc();
for (;!isdigit(c);c=gc()) f^=c=='-';
for (;isdigit(c);c=gc()) x=x*10+c-'0';
x*=f?1:-1;
}
template <typename mitsuha>
inline int write(mitsuha x){
if (!x) return pc(48);
if (x<0) x=-x,pc('-');
re0 bit[20],i,p=0;
for (;x;x/=10) bit[++p]=x%10;
for (i=p;i;--i) pc(bit[i]+48);
}
inline char fuhao(){
rec c=gc();
for (;isspace(c);c=gc());
return c;
}
}using namespace chtholly;
using namespace std;
#define bl(x) (((x)-1)/block+1)
#define ls(x) (((x)-1)*block+1)
#define rs(x) (min((x)*block,n))
const int yuzu=1e5;
typedef int fuko[yuzu|10];
#define all(x) x.begin(),x.end()
int n=read(),m=read(),block,num,sum[1500][1500];
vector<int> pos[yuzu|10];
fuko a,b,cnt;
int query(int l,int r,int x){return upper_bound(all(pos[x]),r)-lower_bound(all(pos[x]),l);}//询问[l,r]内x有多少个.
void buildblock(){
re0 i;
block=sqrt(n/log2(n));
sort(b+1,b+n+1);
num=unique(b+1,b+n+1)-b-1;
for (i=1;i<=n;++i) {
a[i]=lower_bound(b+1,b+num+1,a[i])-b;//离散化并预处理每一个数出现的位置
pos[a[i]].push_back(i);
}
for (i=1;i<=bl(n);++i){//预处理区间[i,j]的众数
memset(cnt,0,sizeof cnt);
int ans=0;
for (re0 j=ls(i);j<=n;++j){
cnt[a[j]]++;
if (cnt[a[j]]>cnt[ans]||cnt[a[j]]==cnt[ans]&&a[j]int main(){
re0 i,t;
for (i=1;i<=n;++i) a[i]=b[i]=read();
buildblock();
int lastans=0;
for (t=1;t<=m;++t){
int l=read(),r=read(),ans,tmp;
l=(l+lastans-1)%n+1,r=(r+lastans-1)%n+1;
if (l>r) swap(l,r);
ans=sum[bl(l)+1][bl(r)-1],tmp=query(l,r,ans);
for (i=l;i<=min(rs(bl(l)),r);++i){
int t=query(l,r,a[i]);
if (t>tmp||t==tmp&&a[i]/*
如果a[i]出现的次数大于已有的众数,或者出现次数相等但是a[i]比已知众数小的话就用a[i]更新ans.
*/
}
if (bl(l)!=bl(r)){
for (i=ls(bl(r));i<=r;++i){
int t=query(l,r,a[i]);
if (t>tmp||t==tmp&&a[i]
Thank you.Yeah!