【BZOJ3809】Gty的二逼妹子序列
3809: Gty的二逼妹子序列
Time Limit: 80 Sec Memory Limit: 28 MBSubmit: 1627 Solved: 481
[Submit][Status][Discuss]
Description
Autumn和Bakser又在研究Gty的妹子序列了!但他们遇到了一个难题。
对于一段妹子们,他们想让你帮忙求出这之内美丽度∈[a,b]的妹子的美丽度的种类数。
为了方便,我们规定妹子们的美丽度全都在[1,n]中。
给定一个长度为n(1<=n<=100000)的正整数序列s(1<=si<=n),对于m(1<=m<=1000000)次询问“l,r,a,b”,每次输出sl...sr中,权值∈[a,b]的权值的种类数。
Input
第一行包括两个整数n,m(1<=n<=100000,1<=m<=1000000),表示数列s中的元素数和询问数。
第二行包括n个整数s1...sn(1<=si<=n)。
接下来m行,每行包括4个整数l,r,a,b(1<=l<=r<=n,1<=a<=b<=n),意义见题目描述。
保证涉及的所有数在C++的int内。
保证输入合法。
Output
对每个询问,单独输出一行,表示sl...sr中权值∈[a,b]的权值的种类数。
Sample Input
10 10
4 4 5 1 4 1 5 1 2 1
5 9 1 2
3 4 7 9
4 4 2 5
2 3 4 7
5 10 4 4
3 9 1 1
1 4 5 9
8 9 3 3
2 2 1 6
8 9 1 4
4 4 5 1 4 1 5 1 2 1
5 9 1 2
3 4 7 9
4 4 2 5
2 3 4 7
5 10 4 4
3 9 1 1
1 4 5 9
8 9 3 3
2 2 1 6
8 9 1 4
Sample Output
2
0
0
2
1
1
1
0
1
2
0
0
2
1
1
1
0
1
2
HINT
样例的部分解释:
5 9 1 2
子序列为4 1 5 1 2
在[1,2]里的权值有1,1,2,有2种,因此答案为2。
3 4 7 9
子序列为5 1
在[7,9]里的权值有5,有1种,因此答案为1。
4 4 2 5
子序列为1
没有权值在[2,5]中的,因此答案为0。
2 3 4 7
子序列为4 5
权值在[4,7]中的有4,5,因此答案为2。
建议使用输入/输出优化。
Source
分块+莫队
我们用一个cnt[j]表示第i个询问时j出现次数
我们维护每个块中有多少个元素(第一次?第一次被查询+第一次出现过),我们只要用val数组记录一下某个块有多少个数被维护
假设我们某一次询问移动l,r导致其减成0,我们就更新答案
具体来说我也不是很懂 %一发Flere825
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
/*To The End Of The Galaxy*/ #include<cstdio> #include<cstdlib> #include<iostream> #include<cstring> #include<algorithm> #include<queue> #include<iomanip> #include<stack> #include<map> #include<set> #include<cmath> #include<complex> #define debug(x) cerr<<#x<<"="<<x<<endl #define INF 0x7f7f7f7f #define llINF 0x7fffffffffffll using namespace std; typedef pair<int,int> pii; typedef long long ll; inline int init() { int now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } inline long long llinit() { long long now=0,ju=1;char c;bool flag=false; while(1) { c=getchar(); if(c=='-')ju=-1; else if(c>='0'&&c<='9') { now=now*10+c-'0'; flag=true; } else if(flag)return now*ju; } } struct node { int l,r,a,b,id,ans; }query[1000101]; int n,m; int bel[100001]; int block,divi; int ans; #define pos(x) (((x-1)/block)+1) bool cmp(node a,node b) { if(pos(a.l)!=pos(b.l)) { return pos(a.l)<pos(b.l); } else return a.r<b.r; } bool cmpid(node a,node b) { return a.id<b.id; } int cnt[100005],val[100005]; int a[100005]; inline void Plus(int p) { cnt[a[p]]++; if(cnt[a[p]]==1)val[bel[a[p]]]++; } inline void Minus(int p) { cnt[a[p]]--; if(cnt[a[p]]==0)val[bel[a[p]]]--; } inline int ask(int l,int r) { int ans=0; if(bel[l]==bel[r]) { for(int i=l;i<=r;i++) { if(cnt[i])ans++; } return ans; } for(int i=l;i<=bel[l]*divi;i++) { if(cnt[i]) { ans++; } } for(int i=((bel[r]-1)*divi)+1;i<=r;i++) { if(cnt[i]) { ans++; } } for(int i=bel[l]+1;i<bel[r];i++) { ans+=val[i]; } return ans; } int main() { int l=1,r=0; n=init();m=init(); block=sqrt(m); divi=sqrt(n); for(int i=1;i<=n;i++) { a[i]=init(); bel[i]=((i-1)/divi)+1; } for(int i=1;i<=m;i++) { query[i].l=init();query[i].r=init();query[i].a=init();query[i].b=init(); query[i].id=i; } sort(query+1,query+1+m,cmp); for(int i=1;i<=m;i++) { if(query[i].r>r) { for(r=r+1;r<=query[i].r;r++) { Plus(r); } } else if(query[i].r<r) { for(;r>query[i].r;r--) { Minus(r); } } if(query[i].l>l) { for(;l<query[i].l;l++) { Minus(l); } } else if(query[i].l<l) { for(l=l-1;l>=query[i].l;l--) { Plus(l); } } l=query[i].l;r=query[i].r; query[i].ans=ask(query[i].a,query[i].b); } sort(query+1,query+1+m,cmpid); for(int i=1;i<=m;i++) { printf("%d\n",query[i].ans); } return 0; } /* srO xudyh davidlee1999WTK linkct1999 Orz compiler TDM-GCC 5.9.2 */