hdu4288 Coder(线段树单点更新)
2014-02-02 22:37
288 查看
题意:支持增删,查操作,最后的序列式递增的。
做法:主要是如何维护mod5的sum值,这里左儿子可以不用管,关键是右儿子的处理,可以假设右儿子有t个节点,左儿子有cnt个节点,
则令(t+cnt)MOD 5= i 则tmod5=(i-cnt MOD 5)MOD 5 ,所以剩下的就是维护每个节点的节点总数以及相应的和就好了。
1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 typedef long long ll;
5 using namespace std;
6 #define lz u<<1,l,mid
7 #define rz u<<1|1,mid+1,r
8 const int MAX = 100000+10;
9 struct node
{
ll sum[6],cnt;
}tree[MAX<<2];
int num[MAX],rnum[MAX],check[MAX];
void build(int u,int l,int r)
{
for(int i=0;i<5;i++) tree[u].sum[i]=0;
tree[u].cnt=0;
if(l!=r)
{
int mid=(l+r)>>1;
build(lz); build(rz);
}
}
void add(int u,int l,int r,int x,int d,int cur)
{
if(l==r)
{
tree[u].sum[1]+=d;
tree[u].cnt+=cur;
return;
}
int mid=(l+r)>>1;
if(x<=mid) add(lz,x,d,cur);
else add(rz,x,d,cur);
tree[u].cnt=tree[u<<1].cnt+tree[u<<1|1].cnt;
for(int i=0;i<5;i++)
{
tree[u].sum[i]=tree[u<<1].sum[i]+tree[u<<1|1].sum[((i-tree[u<<1].cnt)%5+5)%5];
}
}
int main()
{
int n,a; char str[10];
while(scanf("%d",&n)==1)
{
int cur=0;
for(int i=0;i<n;i++)
{
scanf("%s",str);
if(str[0]=='a')
{
check[i]=1;
scanf("%d",&a);
num[i]=rnum[cur++]=a;
}
else if(str[0]=='d')
{
check[i]=2;
scanf("%d",&num[i]);
}
else check[i]=3;
}
sort(rnum,rnum+cur);
int tot=unique(rnum,rnum+cur)-rnum;
if(tot!=0) build(1,1,tot);
for(int i=0;i<n;i++)
{
if(check[i]==1)
{
int pos=lower_bound(rnum,rnum+tot,num[i])-rnum+1;
add(1,1,tot,pos,num[i],1);
}
else if(check[i]==2)
{
int pos=lower_bound(rnum,rnum+tot,num[i])-rnum +1;
add(1,1,tot,pos,-num[i],-1);
}
else
{
if(tot==0) printf("0\n");
else
{
printf("%I64d\n",tree[1].sum[3]);
}
}
}
}
return 0;
}
做法:主要是如何维护mod5的sum值,这里左儿子可以不用管,关键是右儿子的处理,可以假设右儿子有t个节点,左儿子有cnt个节点,
则令(t+cnt)MOD 5= i 则tmod5=(i-cnt MOD 5)MOD 5 ,所以剩下的就是维护每个节点的节点总数以及相应的和就好了。
1 #include<cstring>
2 #include<algorithm>
3 #include<cstdio>
4 typedef long long ll;
5 using namespace std;
6 #define lz u<<1,l,mid
7 #define rz u<<1|1,mid+1,r
8 const int MAX = 100000+10;
9 struct node
{
ll sum[6],cnt;
}tree[MAX<<2];
int num[MAX],rnum[MAX],check[MAX];
void build(int u,int l,int r)
{
for(int i=0;i<5;i++) tree[u].sum[i]=0;
tree[u].cnt=0;
if(l!=r)
{
int mid=(l+r)>>1;
build(lz); build(rz);
}
}
void add(int u,int l,int r,int x,int d,int cur)
{
if(l==r)
{
tree[u].sum[1]+=d;
tree[u].cnt+=cur;
return;
}
int mid=(l+r)>>1;
if(x<=mid) add(lz,x,d,cur);
else add(rz,x,d,cur);
tree[u].cnt=tree[u<<1].cnt+tree[u<<1|1].cnt;
for(int i=0;i<5;i++)
{
tree[u].sum[i]=tree[u<<1].sum[i]+tree[u<<1|1].sum[((i-tree[u<<1].cnt)%5+5)%5];
}
}
int main()
{
int n,a; char str[10];
while(scanf("%d",&n)==1)
{
int cur=0;
for(int i=0;i<n;i++)
{
scanf("%s",str);
if(str[0]=='a')
{
check[i]=1;
scanf("%d",&a);
num[i]=rnum[cur++]=a;
}
else if(str[0]=='d')
{
check[i]=2;
scanf("%d",&num[i]);
}
else check[i]=3;
}
sort(rnum,rnum+cur);
int tot=unique(rnum,rnum+cur)-rnum;
if(tot!=0) build(1,1,tot);
for(int i=0;i<n;i++)
{
if(check[i]==1)
{
int pos=lower_bound(rnum,rnum+tot,num[i])-rnum+1;
add(1,1,tot,pos,num[i],1);
}
else if(check[i]==2)
{
int pos=lower_bound(rnum,rnum+tot,num[i])-rnum +1;
add(1,1,tot,pos,-num[i],-1);
}
else
{
if(tot==0) printf("0\n");
else
{
printf("%I64d\n",tree[1].sum[3]);
}
}
}
}
return 0;
}
相关文章推荐
- hdu4288 Coder 离线线段树 单点更新 区间求和 离散化?
- HDU4288:Coder(线段树单点更新版 && 暴力版)
- HDU4288:Coder(线段树单点更新版 && 暴力版)
- 线段树(单点更新) HDOJ 4288 Coder
- hdu4288之线段树单点更新
- HDU 4288 Coder(线段树单点更新)
- 【HDU4288 Coder】离线+离散化+5颗线段树的更新操作
- HDU 1540——Tunnel Warfare(线段树,区间合并+单点更新+单点查询)
- hdu1754 I Hate It 线段树,单点更新
- hdu2795 Billboard (线段树,单点更新)
- ZOJ - 1610 Count the Colors (线段树单点查询 区间更新)
- POJ 2828 线段树单点更新 离线搞
- HDU—1754—I_Hate_It—【数据结构】【线段树】【单点更新】
- 线段树求区间最大值RMQ(单点更新)
- 线段树单点更新 ants
- HDU1394 Minimum Inversion Number [暴力] [线段树-单点更新]
- .CodeforcesBeta Round #19 D. Points 线段树 单点更新
- HDU 1754 I Hate It(线段树,单点更新,线段查询)
- POJ2828 Buy Tickets 【线段树】+【单点更新】+【逆序】
- hdu1166 线段树单点更新区间查询