3956: Count
Time Limit: 10 Sec Memory Limit: 512 MB
Submit: 524 Solved: 214
[Submit][Status][Discuss]
Description
Input
Output
Sample Input
3 2 0
2 1 2
1 1
1 3
Sample Output
0
3
HINT
M,N<=3*10^5,Ai<=10^9
Source
CH Round#64 MFOI杯水题欢乐赛day1 By Gromah
sol:
感觉自己果然还是弱爆了。这题直观上看好点对是不会有很多组的,具体怎么证我不知道。后来拿个单调递减的栈看了一下,显然top和top-1才会产生一个贡献,所以一个小的点最多只会和左边,右边比他大的点产生一次贡献,那最多是2n组。然后就只要求区间覆盖了。
然后我一开始的想法是预处理一下大力O1回答询问。所以往差分,把询问拆成l-1,r容斥之类的方向思考,结果好像都不能很好解决这个问题。因为我不知道怎么加加减减弄到那个区间内的答案。
后来一个julao告诉我直接主席树就能解决了,一个区间l,在l之后可以查询到r的话就能保证区间被覆盖了
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
int n,m;
inline int read()
{
char c;
int res,flag=0;
while((c=getchar())>'9'||c<'0') if(c=='-')flag=1;
res=c-'0';
while((c=getchar())>='0'&&c<='9') res=(res<<3)+(res<<1)+c-'0';
return flag?-res:res;
}
const int N=310000;
const int M=12100000;
int type,last,l,r;
int sum[M],top,sta[N];
int a[N];
struct cc
{
int x,y;
inline friend bool operator <(const cc &a,const cc &b)
{
return a.x<b.x||a.x==b.x&&a.y<b.y;
}
}b[N*2];
int tot,nonsame,number;
int lc[M],rc[M];
inline void insert(int &x,int y,int l,int r,int pos)
{
x=++number;
sum[x]=sum[y]+1;
lc[x]=lc[y];
rc[x]=rc[y];
if(l==r) return;
int mid=l+r>>1;
if(pos<=mid) insert(lc[x],lc[y],l,mid,pos);
else insert(rc[x],rc[y],mid+1,r,pos);
}
inline int query(int x,int y,int l,int r,int L,int R)
{
if(L<=l&&r<=R) return sum[x]-sum[y];
int mid=l+r>>1,res=0;
if(mid>=L) res+=query(lc[x],lc[y],l,mid,L,R);
if(mid+1<=R) res+=query(rc[x],rc[y],mid+1,r,L,R);
return res;
}
int rt[N],st;
int main()
{
// freopen("3956.in","r",stdin);
// freopen(".out","w",stdout);
n=read();
m=read();
type=read();
for(int i=1;i<=n;++i)
{
a[i]=read();
nonsame=1;
while(top>0&&a[i]>=a[sta[top]])
{
++tot;
b[tot].x=sta[top];
b[tot].y=i;
if(a[i]==a[sta[top]]) nonsame=0;
--top;
}
sta[++top]=i;
if(top>1&&nonsame)
{
++tot;
b[tot].x=sta[top-1];
b[tot].y=i;
}
}
sort(b+1,b+1+tot);
// for(int i=1;i<=tot;++i)
// printf("%d %d\n",b[i].x,b[i].y);
st=1;
for(int i=1;i<=n;++i)
{
rt[i]=rt[i-1];
while(st<=tot&&b[st].x<=i)
{
insert(rt[i],rt[i],1,n,b[st].y);
++st;
}
}
while(m--)
{
l=read();
r=read();
if(type)
{
l=(l+last-1)%n+1;
r=(r+last-1)%n+1;
if(l>r) swap(l,r);
}
printf("%d\n",last=query(rt[r],rt[l-1],1,n,l,r));
}
}