题目链接
题意:维护一个序列。
有两种操作,一种叫做把[l,r]的大于x的数减掉x,
一种是查询[l,r]里面x的出现次数。
真红世界第一可爱(大声
简单粗暴的opt题目
好像整个序列里面的数再怎么变最小也就是0,而且变成0就不会动了
感觉可以分析一波复杂度不过还没有思路好像太早了点
在开始找思路之前先定义一个
(本题数据上界)
查询怎么做?
主席树懒修改的话查询又一定要推到底,那可能要用某种奇怪的姿势搞分块暴力
一个块里面相同的那些数可以做成一个集合,修改其实就是把集合
转移进
。
(当然不能只转一个
,不然待会暴力重构边缘块的时候就凉凉了)
这样暴力的,复杂度好像有点高吧?
那怎么做马?作为一个合格的能过这道题的分块至少也要
这个复杂度真吗?
第一个操作是什么?把
里面大于
的减掉
,
这两个
有没有很玄,想想是不是能够摊还
代表块
的最大值,块的初势就是
有
个块, 想想能不能做到
——也就是付出一点的代价至少让
减少一点
修改的时候吧,对于
里面的块,
如果
就跳过。
,可以消耗
次的费用使
至少减少
。
这个在
的情况下代价等于势能减少量,很阔以
可是
的情况下代价大于势能减少量,这就很不阔以了。
既然
减少的量在这种情况下固定为
了,那代价怎么说也得
吧?
实际上把
的下移相当于把
的上移
然后整体
于是修改的时候把
的拿来加
,给块加一个整体
的标记。
总的复杂度
ps.洛谷上面Input写错了,第二个操作应该是2 l r x,x写成了p(
真实的卡常数大赛
数据范围弱化
听说空间可以压下40M
不过我就不专门开个数据类型了(
Accepted 128076kb
4822B 15396ms
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cctype>
#include<cmath>
#include<ctime>
#define reg register int
#define max(a,b) a>b?a:b
#define min(a,b) a<b?a:b
#define getchar() (frS==frT&&(frT=(frS=frBB)+fread(frBB,1,1<<12,stdin),frS==frT)?EOF:*frS++)
using namespace std;
char frBB[1<<12],*frS=frBB,*frT=frBB;
inline int read()
{
int x=0;char ch=0;
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))x=x*10+ch-48,ch=getchar();
return x;
}
template<typename T>
inline void write(T x)
{
if(x>9)write(x/10);
putchar(x%10+48);
}
int N,M,siz,cnt,t;
int Ai[100005]={};
int lb[320]={},rb[320]={};
short belong[100005]={};
int root[320][100005]={};
int sub[320]={};
int mx[320]={};
int fa[100005]={};
int roottype[100005]={};
int rootcnt[100005]={};
inline int find(const int&x){return (fa[x]==x)?x:(fa[x]=find(fa[x]));}
inline void merge(const int&id,const int&a,const int&b)
{
if(!root[id][b])
{
root[id][b]=root[id][a];
roottype[root[id][a]]=b;
}
else
{
fa[root[id][a]]=root[id][b];
rootcnt[root[id][b]]+=rootcnt[root[id][a]];
}
root[id][a]=0;
}
inline void preload(const reg&id)
{
mx[id]=0;
for(reg i=lb[id];i<=rb[id];++i)
{
mx[id]=max(mx[id],Ai[i]);
rootcnt[i]=1;
if(!root[id][Ai[i]])
{
root[id][Ai[i]]=i;
fa[i]=i;
roottype[i]=Ai[i];
}
else
{
fa[i]=root[id][Ai[i]];
rootcnt[fa[i]]+=rootcnt[i];
}
}
}
inline void _clear(const reg&id)
{
for(reg i=lb[id];i<=rb[id];++i)
{
Ai[i]=roottype[find(i)];
root[id][Ai[i]]=0;
Ai[i]-=sub[id];
}
for(reg i=lb[id];i<=rb[id];++i)fa[i]=0;
sub[id]=0;
}
inline void work(const reg&id,const reg&x)
{
if(mx[id]-sub[id]<=x)return;
if(mx[id]-sub[id]<2*x)
{
for(reg i=sub[id]+x+1;i<=mx[id];++i)if(root[id][i])merge(id,i,i-x);
mx[id]=min(mx[id],x+sub[id]);
}
else
{
for(reg i=sub[id]+1;i<=sub[id]+x;++i)if(root[id][i])merge(id,i,i+x);
sub[id]+=x;
}
}
inline void modify(const reg&l,const reg&r,const reg&x)
{
reg lblock=belong[l],rblock=belong[r];
if(lblock==rblock)
{
_clear(lblock);
for(reg i=l;i<=r;++i)if(Ai[i]>x)Ai[i]-=x;
preload(lblock);
}
else
{
_clear(lblock); _clear(rblock);
for(reg i=l;i<=rb[lblock];++i)if(Ai[i]>x)Ai[i]-=x;
for(reg i=lblock+1;i<rblock;++i)work(i,x);
for(reg i=lb[rblock];i<=r;++i)if(Ai[i]>x)Ai[i]-=x;
preload(lblock); preload(rblock);
}
}
inline int query(const reg&l,const reg&r,const reg&x)
{
reg lblock=belong[l],rblock=belong[r],ret=0;
if(lblock!=rblock)
{
t=x+sub[lblock];
for(reg i=l;i<=rb[lblock];++i)if(roottype[find(i)]==t)++ret;
t=x+sub[rblock];
for(reg i=lb[rblock];i<=r;++i)if(roottype[find(i)]==t)++ret;
for(reg i=lblock+1;i<rblock;++i)if(x<=mx[i]-sub[i])ret+=rootcnt[root[i][x+sub[i]]];
}
else
{
for(reg i=l;i<=r;++i)
{
if(roottype[find(i)]==x+sub[lblock])++ret;
}
}
return ret;
}
#define read() read()
#define write(x) write(x)
#define find(x) find(x)
#define merge(id,a,b) merge(id,a,b)
#define preload(id) preload(id)
#define _clear(id) _clear(id)
#define work(id,x) work(id,x)
#define modify(l,r,x) modify(l,r,x)
int main()
{
N=read(); M=read(); siz=sqrt(N); cnt=(N-1)/siz+1;
for(reg i=1;i<=N;++i)Ai[i]=read();
for(reg i=1;i<=cnt;++i)
{
lb[i]=(i-1)*siz+1;
rb[i]=i*siz;
if(i==cnt)rb[i]=N;
for(reg j=lb[i];j<=rb[i];++j)
{
rootcnt[j]=1;
belong[j]=i;;
mx[i]=max(mx[i],Ai[j]);
if(!root[i][Ai[j]])
{
fa[j]=j;
root[i][Ai[j]]=j;
roottype[j]=Ai[j];
}
else
{
fa[j]=root[i][Ai[j]];
rootcnt[fa[j]]+=rootcnt[j];
}
}
}
reg opt,l,r,x;
while(M--)
{
opt=read(); l=read(); r=read(); x=read();
if(opt==1)modify(l,r,x);
if(opt==2)write(query(l,r,x)),putchar('\n');
}
return 0;
}
F社咕咕咕
等两个月不知道能不能看见新作