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;
}