刚写完了一道杭电的Necklace【HDU 3874】变深有感触,就趁热打铁做了这道图灵树(翻译过来)的题,不过这道题有个坑点就是怎么处理RE的问题?很多人——那些大佬,都是想到了用离散化来解决问题,而我不同(或许就是经常这样投机造成了我不是大佬吧),我想到的做法是用一个map去存每一个数(庆幸这题不会超memory),存的每一个数返回的是他们的地址,思路与这道题,就是Necklace做法相同,可以先做那一道在过来考虑这道题,毕竟是升华版本。
题目链接
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef long long ll;
struct node
{
int l,r,id;
}q[100005]; //询问的数组,记录用
bool cmp(node e1, node e2)
{
return e1.r<e2.r; //按照右端升序排序,这样可以不断更新重复出现的值(先出现的更新为0)
}
int N,M; //N:1~30000 M:1~100000
ll val[30005]; //此点的值
ll bit[200005]; //树状数组
ll pos[30005]; //这点的上一个与它值相等的点,若没有则为0
map<ll, ll>loc; //记录目前价值的点的所在位置,便于下次找上个相同值节点的位置
ll ans[100005]; //答案记录的数组
void update(int i, ll x) //更新
{
while(i<=N+1)
{
bit[i]+=x;
i+=lowbit(i);
}
}
ll Query(int i) //查找
{
ll res=0;
while(i)
{
res+=bit[i];
i-=lowbit(i);
}
return res;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(val, 0, sizeof(val));
memset(bit, 0, sizeof(bit));
memset(pos, 0, sizeof(pos));
loc.clear();
scanf("%d",&N);
for(int i=1; i<=N; i++)
{
scanf("%lld",&val[i]);
pos[i]=loc[val[i]];
loc[val[i]]=i;
update(i, val[i]);
}
scanf("%d",&M);
for(int i=1; i<=M; i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1, q+1+M, cmp);
int r=0;
for(int i=1; i<=M; i++)
{
for(int j=r+1; j<=q[i].r; j++)
{
if(pos[j])
{
update(pos[j], -val[j]);
}
}
r=q[i].r;
ans[q[i].id]=Query(q[i].r)-Query(q[i].l-1);
}
for(int i=1; i<=M; i++) printf("%lld\n",ans[i]);
}
return 0;
}