bzoj 3809 Gtyの二強制妹シーケンス
22738 ワード
テーマ
n個の要素の配列、元素サイズ∈[1,n]は、[l,r]に問い合わせるたびに、数値[s,t]にどれぐらいのn<=1 e 5,m<=1 e 6]が現れますか?
問題を解く
発見しやすいのは、チームを作って樹状の配列で維持するという複雑さです.O(n\m l o g n)O(n\sqrt m logn)O(nm logn)です.Tにするべきです.実は専用に送ってみました.確かにTです.nとmの違いに注目して、必要な操作を分析します.二回前に私達が木の形の配列でメンテナンスすると、これらは全部lognです.私達は2の複雑さを犠牲にして1の複雑度を下げることを考えています.ブロックを分けて、私達は分塊で値を維持します.すると、挿入はO(1)O(1)O(n)O(n)O(n)O(n)O)O(n)O)O(n)O)O(n)O)O)O)O(n)O)O)O)O(n)O)O(n)O)O)O)O(n)O)O)O(n)O)O)O)O(n)Oメモリ制限狂気病…
n個の要素の配列、元素サイズ∈[1,n]は、[l,r]に問い合わせるたびに、数値[s,t]にどれぐらいのn<=1 e 5,m<=1 e 6]が現れますか?
問題を解く
発見しやすいのは、チームを作って樹状の配列で維持するという複雑さです.O(n\m l o g n)O(n\sqrt m logn)O(nm logn)です.Tにするべきです.実は専用に送ってみました.確かにTです.nとmの違いに注目して、必要な操作を分析します.二回前に私達が木の形の配列でメンテナンスすると、これらは全部lognです.私達は2の複雑さを犠牲にして1の複雑度を下げることを考えています.ブロックを分けて、私達は分塊で値を維持します.すると、挿入はO(1)O(1)O(n)O(n)O(n)O(n)O)O(n)O)O(n)O)O(n)O)O)O)O(n)O)O)O)O(n)O)O(n)O)O)O)O(n)O)O)O(n)O)O)O)O(n)Oメモリ制限狂気病…
#include
#include
#include
#include
using namespace std;
const int N=100005,M=1000005;
struct node{
int l,r,s,t,pos;
}q[M];
int a[N];
int block[N];
bool cmp(node a,node b){
if(block[a.l]!=block[b.l])
return block[a.l]<block[b.l];
return a.r<b.r;
}
int cnt[N];
int sum[N];
void Add(int x){
if(cnt[x]==0){
sum[block[x]]++;
}
cnt[x]++;
}
void Delete(int x){
cnt[x]--;
if(cnt[x]==0)
sum[block[x]]--;
}
int Query(int x,int y){
int res=0;
if(block[y]-block[x]<=1){
for(int i=x;i<=y;i++)
res+=cnt[i]>0;
return res;
}
for(int i=block[x]+1;i<=block[y]-1;i++)
res+=sum[i];
for(int i=x;block[i]==block[x];i++)
res+=cnt[i]>0;
for(int i=y;block[i]==block[y];i--)
res+=cnt[i]>0;
return res;
}
int n,m;
int ans[M];
void Read(int &x){
x=0;
char c=getchar();
while(c<'0'||c>'9')
c=getchar();
while(c>='0'&&c<='9')
x=x*10+c-'0',c=getchar();
}
int main()
{
Read(n),Read(m);
//scanf("%d%d",&n,&m);
int S=sqrt(n);
for(int i=1;i<=n;i++)
block[i]=(i-1)/S+1;
for(int i=1;i<=n;i++){
Read(a[i]);
//scanf("%d",&a[i]);
}
for(int i=1;i<=m;i++){
Read(q[i].l),Read(q[i].r),Read(q[i].s),Read(q[i].t);
//scanf("%d%d%d%d",&q[i].l,&q[i].r,&q[i].s,&q[i].t);
q[i].pos=i;
}
sort(q+1,q+m+1,cmp);
int l=1,r=0;
for(int i=1;i<=m;i++){
int ql=q[i].l,qr=q[i].r;
while(l>ql){
l--;
Add(a[l]);
}
while(r<qr){
r++;
Add(a[r]);
}
while(l<ql){
Delete(a[l]);
l++;
}
while(r>qr){
Delete(a[r]);
r--;
}
ans[q[i].pos]=Query(q[i].s,q[i].t);
}
for(int i=1;i<=m;i++)
printf("%d
",ans[i]);
}