1. 程式人生 > >牛客網暑期ACM多校訓練營(第一場)- J Different Integers (莫隊)

牛客網暑期ACM多校訓練營(第一場)- J Different Integers (莫隊)

url namespace div struct different operator truct -- eof

題意:裸的莫隊題,每個查詢Li,Ri,返回區間[1,Li]和[Ri,N]區間中不同的數的個數。

分析:正常的離線查詢,是求區間[Li,Ri]中要求的答案,而該題所求答案為外側兩個區間中的答案,那麽cnt[i]維護的東西修改一下即可。對查詢排序的時候,將R較大的排在前面,因為對於所維護的區間,是從兩側往內遞推過來的,這樣才能令不必要的遞推減少。

此外,也有用主席樹和樹狀數組的做法。

#include<bits/stdc++.h>
using namespace std;
const int maxn =1e5+5;
int pos[maxn];
struct Query{
    int
L,R,id; bool operator <(const Query q) const{ if(pos[L]==pos[q.L]) return R>q.R; return pos[L]<pos[q.L]; } }Q[maxn]; int a[maxn]; int ans[maxn]; int block; int cnt[maxn]; int vis[maxn]; int res; //區間是相反的 void add(int pos) { cnt[a[pos]]++; if(cnt[a[pos]]==1) res++; }
void pop(int pos){ cnt[a[pos]]--; if(cnt[a[pos]]==0) res--; } int main() { int n,q; while(scanf("%d%d",&n,&q)==2){ memset(cnt,0,sizeof(cnt)); block =ceil(sqrt(1.0*n)); for(int i=1;i<=n;++i){ scanf("%d",&a[i]); pos[i]
= i/block; } for(int i=1;i<=q;++i){ scanf("%d%d",&Q[i].L,&Q[i].R); Q[i].id = i; } sort(Q+1,Q+q+1); int curL=0,curR=n+1; res=0; for(int i=1;i<=q;++i){ //外區間縮 while(curL>Q[i].L) pop(curL--); while(curR<Q[i].R) pop(curR++); //外區間擴 while(curL<Q[i].L) add(++curL); while(curR>Q[i].R) add(--curR); ans[Q[i].id] = res; } for(int i=1;i<=q;++i){ printf("%d\n",ans[i]); } } }

牛客網暑期ACM多校訓練營(第一場)- J Different Integers (莫隊)