题意:

维护一个有序数列{An},有三种操作:


1、添加一个元素。


2、删除一个元素。


3、求数列中下标%5 = 3的值的和。

解题思路:
看的各种题解,今天终于弄懂了。
由于线段树中不支持添加、删除操作,所以题解写的是用离线做法。
我们来看它是如何解决添加、删除的问题的。
首先将所有出现过的数记录下来,然后排序去重,最后根据去重结果建树,然后每个操作数都会对应线段树中的一个点。
遇到添加、删除操作的时候,只要把那个节点的值改变,然后将它对下标的影响处理好就可以。
那么如何处理这些操作对下标的影响呢?
现在我们考虑一个父区间,假设它的左右子区间已经更新完毕。
显然,左区间中下标%5的情况与父区间中%5的情况完全相同;
可是,右区间中却不一定相同,因为右区间中的下标是以 mid 当作 1 开始的。
那么,只要我们知道左区间中有效元素的个数 cnt,我们就能知道右区间中的下标 i 在父区间中对应的下标为 i+cnt。
所以,虽然我们最终要的只是总区间中下标%5 = 3的和。但是在更新时我们需要知道右区间%5的所有情况。
于是我们要在线段树的每个节点开一个 sum[5] 和一个 cnt,分别记录这个节点中下标%5的5种情况的和与有效元素的个数。
而查询时,直接访问总区间的 sum[3] 即可。
如此,题目便可解了。复杂度O(M logN logN)。

以前用的是线段树,这次用暴力来了一发

 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
using namespace std;
#define MOD 1000000007
const int INF=0x3f3f3f3f;
const double eps=1e-;
typedef long long ll;
#define cl(a) memset(a,0,sizeof(a))
#define ts printf("*****\n");
const int N=;
int n,m,tt;
int main()
{
int i,j,k,ca=;
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
while(scanf("%d",&n)!=EOF)
{
int len=;
vector<int> vc;
int x;
vector<int>::iterator it;
char s[];
while(n--)
{
scanf("%s",s);
if(s[]=='a')
{
len++;
scanf("%d",&x);
it=lower_bound(vc.begin(),vc.end(),x);
vc.insert(it,x);
}
else if(s[]=='d')
{
len--;
scanf("%d",&x);
it=lower_bound(vc.begin(),vc.end(),x);
vc.erase(it);
}
else
{
ll sum=;
for(i=;i<len;i+=)
{
sum+=vc[i];
}
printf("%I64d\n",sum);
}
}
}
}
 #include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define root 1,n,1
#define mid ((l+r)>>1)
#define ll long long
#define cl(a) memset(a,0,sizeof(a))
#define ts printf("*****\n");
using namespace std;
const int MAXN=;
ll sum[MAXN<<][];
vector<int> num;
int cnt[MAXN<<],val[MAXN];
char cz[MAXN],s[];
int n,m,t;
int getid(int v)
{
return lower_bound(num.begin(),num.end(),v)-num.begin()+;
}
void pushup(int rt)
{
cnt[rt]=cnt[rt<<]+cnt[rt<<|];
for(int i=;i<;i++) sum[rt][i]=sum[rt<<][i];
for(int i=;i<;i++) sum[rt][(i+cnt[rt<<])%]+=sum[rt<<|][i]; //这两个不能放一起,找了好长时间
}
int tot=;
void update(int pos,int v,int l,int r,int rt)
{
if(l==r)
{
sum[rt][]=num[pos-]*v;
cnt[rt]=v;
return;
}
if(pos<=mid) update(pos,v,lson);
else update(pos,v,rson);
pushup(rt);
}
int main()
{
int i,j,k,q;
#ifndef ONLINE_JUDGE
freopen("1.in","r",stdin);
#endif
while(~scanf("%d",&n))
{
num.clear();
for(i=;i<=n;i++)
{
scanf("%s",s);
cz[i]=s[];
if(s[]!='s')
{
scanf("%d",val+i);
num.push_back(val[i]);
}
}
cl(sum),cl(cnt);
sort(num.begin(),num.end());
num.erase(unique(num.begin(),num.end()),num.end());
int sumn=num.size();
for(int i=;i<=n;i++)
{
if(cz[i] == 'a') update(getid(val[i]),,,sumn,);
else if(cz[i] == 'd') update(getid(val[i]),,,sumn,);
else printf("%I64d\n",sum[][]);
}
}
return ;
}

hdu 4288 线段树 暴力 **的更多相关文章

  1. hdu 6430 线段树 暴力维护

    Problem E. TeaTree Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Oth ...

  2. V - Can you answer these queries? HDU - 4027 线段树 暴力

    V - Can you answer these queries? HDU - 4027 这个题目开始没什么思路,因为不知道要怎么去区间更新这个开根号. 然后稍微看了一下题解,因为每一个数开根号最多开 ...

  3. hdu 4288 线段树+离线+离散化

    http://acm.hdu.edu.cn/showproblem.php?pid=4288 開始的时候,果断TLE,做的方法是,线段树上只维护%5==3的坐标,比方1 2 3 4 5 6 7  假设 ...

  4. HDU 4288 线段树+离散化

    题意: n个操作 在[1, 100000]  的区间上add 或del数( 必不会重复添加或删除不存在的数) sum 求出整个集合中 (下标%5 == 3 位置) 的数   的和 注意数据类型要64位 ...

  5. hdu 5877 线段树(2016 ACM/ICPC Asia Regional Dalian Online)

    Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  6. hdu 3974 线段树 将树弄到区间上

    Assign the task Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  7. hdu 3436 线段树 一顿操作

    Queue-jumpers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) To ...

  8. hdu 3397 线段树双标记

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  9. hdu 4578 线段树(标记处理)

    Transformation Time Limit: 15000/8000 MS (Java/Others)    Memory Limit: 65535/65536 K (Java/Others) ...

随机推荐

  1. chkconfig用法 LINUX

    chkconfig用法 有时候为了方便管理,我们常常喜欢在Linux中将之安装为服务,然后就可以使用服务来管理. 但是当我们运行安装服务的命令时候,假设服务名为myservice #chkconfig ...

  2. 转一篇Xcode中利用target编译不同版本的文章

    http://www.cocoachina.com/ios/20160331/15832.html 主要说的是,不用自己定义debug宏,而是在xcode的编译配置文件中,设定debug宏,这样,不用 ...

  3. Python~if,while,for~顺序,判断,循环

    if A: for -in : while x: if A:elif:else:       不能直接用int进行迭代,而必须加个range.     range(len(L))     int ob ...

  4. [Android] ListView中如何让onClick和onItemClick事件共存

    ListView中如何使用Button,让onClick和onItemClick事件共存 假如ListView的一条记录包含一个TextView文本框,一个Button按钮,怎样能让点击按钮有事件响应 ...

  5. JS 异步加载的方法

    (1) defer,只支持IE : <script type="text/javascript" defer="defer"> </scrip ...

  6. 【leetcode】 Letter Combinations of a Phone Number(middle)

    Given a digit string, return all possible letter combinations that the number could represent. A map ...

  7. 解决SQL Server的cannot resolve the collation conflict问题

    当没有牵涉到两个不同的数据库时,出现以上错误.   Cannot resolve the collation conflict between "Chinese_PRC_CI_AS" ...

  8. iOS学习资源个人整理

    1208更新: http://www.tuyiyi.com                                    图翼网 https://github.com/Alamofire/Al ...

  9. 模拟赛1029d1

    第二题[题目描述]给你两个日期,问这两个日期差了多少毫秒.[输入格式]两行,每行一个日期,日期格式保证为"YYYY-MM-DD hh:mm:ss"这种形式.第二个日期时间一定比第一 ...

  10. Android错误:Re-installation failed due to different application signatures

    Re-installation failed due to different application signatures (2013-04-20 14:27:32) 转载▼ 标签: 解决方法 问题 ...