J-Different Integers
題意很清楚啦,就是找兩邊區間不同數字的個數,還是自己菜啦,我一眼瞅上去感覺是莫隊,主要原因是我昨天剛剛學習了qsc的莫隊算法視頻,以爲只有查詢操作,沒有修改操作,用莫隊就好啦,沒想到T到懷疑人生,最後可能是服務器的問題吧,我莫隊調整了常數,卡過去啦,不管咋說,還是要把代碼貼一下,紀念自己第一個莫隊算法題目(雖然還是T啦),謝謝叉姐。
代碼(莫隊):
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn = 2e5+7;
struct node {
ll l, r, id;
} Q[maxn];
ll n, m, k, q;
int pos[maxn];
ll a[maxn], ans[maxn], ANS = 0, cnt = 0;
int mp[maxn];
bool cmp(node a, node b)
{
if(pos[a.l] == pos[b.l]) return a.r < b.r;
else return pos[a.l] < pos[b.l];
}
int L = 1, R = 0;
ll rd(){
ll x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void adds(int x)
{
if(mp[a[x]] == 0) {
ANS++;
}
mp[a[x]]++;
}
void del(int x)
{
mp[a[x]]--;
if(mp[a[x]] == 0) {
ANS--;
}
}
int main()
{
while(~scanf("%lld%lld", &n, &q))
{
cnt = 0;
memset(mp, 0, sizeof(mp));
int sz = sqrt(maxn); //改改就過了
for(int i = 1; i <= n; i++)
{
a[i] = rd();
if(mp[a[i]] == 0) {
mp[a[i]]++;
cnt++;
}
else mp[a[i]]++;
pos[i] = i/sz;
}
int cas = 0;
for(int i = 1; i <= q; i++)
{
ll l, r;
l = rd();
r = rd();
if(l >= (r - 1)) {
ans[i] = cnt;
} else {
Q[cas].l = l;
Q[cas].r = r;
Q[cas++].id = i;
}
}
sort(Q, Q+cas, cmp);
ANS = cnt;
L = Q[0].l;
R = Q[0].l+1;
//for(int i = L + 1; i < R; i++) del(i); ans[Q[0].id] = ANS;
for(int i = 0; i < cas; i++)
{
while(L < Q[i].l)
{
L++;
adds(L);
}
while(L > Q[i].l)
{
del(L);
L--;
}
while(R < Q[i].r)
{
del(R);
R++;
}
while(R > Q[i].r)
{
R--;
adds(R);
}
ans[Q[i].id] = ANS;
}
//cout << "1" << endl;
for(int i = 1; i <= q; i++) printf("%lld\n", ans[i]);
}
return 0;
}
題解是說用樹狀數組維護一下就可以啦,又學習了一下樹狀數組:
這裏就直接借用啦題解的文字,學習好算法就好啦,解題思路也要認真學習一下,真正的學習了樹狀數組的維護,學習啦;
利用樹狀數組的維護,這樣子可以在log時間複雜度內將失去的數字減去;
代碼(樹狀數組):
#include<bits/stdc++.h>
const int maxn = 1e6+7;
using namespace std;
int n, q, cnt = 0, tot = 0;
struct Quary{
int l, r, id;
} Q[maxn];
bool cmp(Quary a, Quary b)
{
return a.r < b.r;
}
int main()
{
freopen("in.txt", "r", stdin);
while(~scanf("%d%d", &n, &q))
{
cnt = 0;
tot = 0;
vector<int> a(n+1), first(n+1, -1), last(n+1), result(q+1), count(n+1);
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
last[a[i]] = i;
if(first[a[i]] == -1) {
first[a[i]] = i;
cnt++;
}
}
for(int i = 0; i < q; i++)
{
int l, r; scanf("%d%d", &l, &r);
if(l>=(r-1)) result[i] = cnt;
else {
Q[tot].l = l;
Q[tot].r = r;
Q[tot++].id = i;
}
}
sort(Q, Q+tot, cmp);
for(int i = 1, k = 0; i <= n; i++)
{
while(k < tot&&Q[k].r == i)
{
int &ret = result[Q[k].id] = cnt;
for(int j = Q[k].l; j < i; j += j&(-j)) ret -= count[j];
k++;
}
if(last[a[i]] == i)
{
for(int j = first[a[i]] - 1; j > 0; j -= j&(-j))
count[j]++;
}
}
for(int i = 0; i < q; i++) printf("%d\n", result[i]);
}
return 0;
}