您的位置:首页 > 其它

HDU 3333 Turing tree 用了一发map容器加线段树

2013-10-20 00:24 429 查看
这个题涨姿势了,,,,没考虑把答案全放在一起输出。。。。。如果想到这样就好处理了,先把询问按照右端点升序排序。。然后每一次把端点前的所有值插入,插入的时候先判断当前数有没有插入过,如果插入过,那么把以前插入的删掉,然后再插入到当前位置。就这样一直插下去。然后全部插完了之后就询问。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
using namespace std;
long long dp[300005];
long long ans[300005];
#define lc l,m,index<<1
#define rc m+1,r,index<<1|1
struct node
{
int x,y,num;
}a[300005];
long long cnt[300005<<2];
bool cmp(node a,node b)
{
if(a.y<b.y)
return true;
else
return false;
}
void find(int l,int r,int index,int id)
{
if(l==r)
{
cnt[index]=0;
return ;
}
int m=(l+r)>>1;
if(id<=m)
find(lc,id);
else
find(rc,id);
cnt[index]=cnt[index<<1]+cnt[index<<1|1];
}
void build(int l,int r,int index,int id,long long num)
{
if(l==r)
{
cnt[index]=num;
return;
}
int m=(l+r)>>1;
if(id<=m)
build(lc,id,num);
else
build(rc,id,num);
cnt[index]=cnt[index<<1]+cnt[index<<1|1];
}
long long query(int l,int r,int index,int L,int R)
{
int m=(l+r)>>1;
if(L==l && R==r)
return cnt[index];
if(L>m)
return query(rc,L,R);
else if(R<=m)
return query(lc,L,R);
else return query(lc,L,m)+query(rc,m+1,R);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
map<int,int>mpt;
memset(cnt,0,sizeof(cnt));
int q=0;
int n,m;
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%I64d",&dp[i]);
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d%d",&a[i].x,&a[i].y);
a[i].num=i;
}
sort(a,a+m,cmp);
for(int i=0;i<m;i++)
{
if(a[i-1].y!=a[i].y || i==0)
{
int h;
if(i==0)
h=0;
else
h=a[i-1].y;
for(int j=h;j<a[i].y;j++)
{

if(mpt.count(dp[j]))
find(0,n,1,mpt[dp[j]]);
mpt[dp[j]]=j;
build(0,n,1,j,dp[j]);
}
}
long long ll=query(0,n,1,a[i].x-1,a[i].y-1);
ans[a[i].num]=ll;
}
for(int i=0;i<m;i++)
printf("%I64d\n",ans[i]);
}
// system("pause");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: