hdu3333
题目戳我
题意:给你长度为n的数组,有m次询问,每次询问查询区间内不重复数之和
分析:
1)由于 n<=30000,而数组元素大小<=1e9,故有必要离散化一下,或者用map
2)首先我们对询问区间按右端点升序排序,然后对数组依次进行处理,如果当前元素未在之前出现过,则将它更新进树状数组中并记录该数出现在数组的位置;若出现了,首先将其删除(之前已经记录了位置),再重新将其更新进树状数组中。
3) 对于查询,只要处理到与区间右端点相等时,即可对其进行处理,答案=sum[r]-sum[l-1],记录答案,最后输出
代码
#include<bits/stdc++.h>
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=3e4+5;
struct Node
{
int l,r,k;
}q[100005];
bool cmp2(Node A,Node B){if(A.r==B.r)return A.l<B.l;else return A.r<B.r;}
ll tree[maxn],c[100005];
int b[maxn],a[maxn],vis[maxn];
int n,m;
int lowbit(int x)
{
return x&(-x);
}
void modify(int x,int add)
{
for(int i=x;i<=n;i+=lowbit(i)){
tree[i]+=add;
}
}
ll getsum(int x)
{
ll ans=0;
for(int i=x;i>=1;i-=lowbit(i)){
ans+=tree[i];
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i];
}
scanf("%d",&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&q[i].l,&q[i].r);
q[i].k=i;
}
sort(b+1,b+n+1);
for(int i=1;i<=n;i++){
a[i]=lower_bound(b+1,b+n+1,a[i])-b;
}
sort(q+1,q+m+1,cmp2);
mem(vis,0);mem(tree,0);
int tot=1;
for(int i=1;i<=n;i++){
if(!vis[a[i]]){
modify(i,b[a[i]]);vis[a[i]]=i;
}
else{
modify(vis[a[i]],-b[a[i]]);
modify(i,b[a[i]]);vis[a[i]]=i;
}
while(tot<=m&&q[tot].r==i){
c[q[tot].k]=getsum(q[tot].r)-getsum(q[tot].l-1);tot++;
}
}
for(int i=1;i<=m;i++){
printf("%lld\n",c[i]);
}
}
return 0;
}
hdu4417
题目戳我
题意:长度为n的数组,Mario跳的最高距离为H,m次询问,询问区间内他能跳过的数目
分析:
先将路线上的点和区间的高度进行升序排序,当当前路线上点的高度小于等于区间高度时直接加入到树状数组中,否则开始进行区间统计有多少符合题意得即可。
#include<bits/stdc++.h>
#define ll long long
#define pii pair<int,int>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e5+5;
struct Node
{
int l,r,k,h;
}q[maxn];
bool cmp2(Node A,Node B){return A.h<B.h;}
bool cmp1(pii A,pii B){if(A.first==B.first)return A.second<B.second;else return A.first<B.first;}
int tree[maxn],c[maxn];
pii a[maxn];
int n,m;
int lowbit(int x)
{
return x&(-x);
}
void modify(int x)
{
for(int i=x;i<=n;i+=lowbit(i)){
tree[i]++;
}
}
int getsum(int x)
{
int ans=0;
for(int i=x;i>=1;i-=lowbit(i)){
ans+=tree[i];
}
return ans;
}
int main()
{
int t,Case=0;
scanf("%d",&t);
while(t--){
printf("Case %d:\n",++Case);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i].first);
a[i].second=i;
}
for(int i=1;i<=m;i++){
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].h);
q[i].k=i;q[i].l++;q[i].r++;
}
sort(a+1,a+n+1,cmp1);
sort(q+1,q+m+1,cmp2);
int id=1;
mem(tree,0);
for(int i=1;i<=m;i++){
while(a[id].first<=q[i].h&&id<=n){
modify(a[id].second);id++;
}
c[q[i].k]=getsum(q[i].r)-getsum(q[i].l-1);
}
for(int i=1;i<=m;i++){
printf("%d\n",c[i]);
}
}
return 0;
}