hdu 4288 线段树 暴力 **

题意:

维护一个有序数列{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)。

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

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 #include<map>
 8 using namespace std;
 9 #define MOD 1000000007
10 const int INF=0x3f3f3f3f;
11 const double eps=1e-5;
12 typedef long long ll;
13 #define cl(a) memset(a,0,sizeof(a))
14 #define ts printf("*****\n");
15 const int N=51005;
16 int n,m,tt;
17 int main()
18 {
19     int i,j,k,ca=1;
20     #ifndef ONLINE_JUDGE
21     freopen("1.in","r",stdin);
22     #endif
23     while(scanf("%d",&n)!=EOF)
24     {
25         int len=0;
26         vector<int> vc;
27         int x;
28         vector<int>::iterator it;
29         char s[10];
30         while(n--)
31         {
32             scanf("%s",s);
33             if(s[0]==‘a‘)
34             {
35                 len++;
36                 scanf("%d",&x);
37                 it=lower_bound(vc.begin(),vc.end(),x);
38                 vc.insert(it,x);
39             }
40             else if(s[0]==‘d‘)
41             {
42                 len--;
43                 scanf("%d",&x);
44                 it=lower_bound(vc.begin(),vc.end(),x);
45                 vc.erase(it);
46             }
47             else
48             {
49                 ll sum=0;
50                 for(i=2;i<len;i+=5)
51                 {
52                     sum+=vc[i];
53                 }
54                 printf("%I64d\n",sum);
55             }
56         }
57     }
58 }

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<queue>
 7 #define lson l,mid,rt<<1
 8 #define rson mid+1,r,rt<<1|1
 9 #define root 1,n,1
10 #define mid ((l+r)>>1)
11 #define ll long long
12 #define cl(a) memset(a,0,sizeof(a))
13 #define ts printf("*****\n");
14 using namespace std;
15 const int MAXN=100005;
16 ll sum[MAXN<<2][5];
17 vector<int> num;
18 int cnt[MAXN<<2],val[MAXN];
19 char cz[MAXN],s[1024];
20 int n,m,t;
21 int getid(int v)
22 {
23     return lower_bound(num.begin(),num.end(),v)-num.begin()+1;
24 }
25 void pushup(int rt)
26 {
27     cnt[rt]=cnt[rt<<1]+cnt[rt<<1|1];
28     for(int i=0;i<5;i++) sum[rt][i]=sum[rt<<1][i];
29     for(int i=0;i<5;i++) sum[rt][(i+cnt[rt<<1])%5]+=sum[rt<<1|1][i];    //这两个不能放一起,找了好长时间
30 }
31 int tot=0;
32 void update(int pos,int v,int l,int r,int rt)
33 {
34     if(l==r)
35     {
36         sum[rt][1]=num[pos-1]*v;
37         cnt[rt]=v;
38         return;
39     }
40     if(pos<=mid)    update(pos,v,lson);
41     else    update(pos,v,rson);
42     pushup(rt);
43 }
44 int main()
45 {
46     int i,j,k,q;
47     #ifndef ONLINE_JUDGE
48     freopen("1.in","r",stdin);
49     #endif
50     while(~scanf("%d",&n))
51     {
52         num.clear();
53         for(i=1;i<=n;i++)
54         {
55             scanf("%s",s);
56             cz[i]=s[0];
57             if(s[0]!=‘s‘)
58             {
59                 scanf("%d",val+i);
60                 num.push_back(val[i]);
61             }
62         }
63         cl(sum),cl(cnt);
64         sort(num.begin(),num.end());
65         num.erase(unique(num.begin(),num.end()),num.end());
66         int sumn=num.size();
67         for(int i=1;i<=n;i++)
68         {
69             if(cz[i] == ‘a‘) update(getid(val[i]),1,1,sumn,1);
70             else if(cz[i] == ‘d‘) update(getid(val[i]),0,1,sumn,1);
71             else printf("%I64d\n",sum[1][3]);
72         }
73     }
74     return 0;
75 }
时间: 2024-10-11 17:58:50

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

HDU 4902 线段树||暴力

给定一个序列,两种操作 1:把一段变成x. 2:把一段每个数字,如果他大于x,就变成他和x的gcd,求变换完后,最后的序列. 线段树解法:用lazy标记下即可,优化方法还是很巧妙的, Accepted 4902 515MS 3308K 1941 B C++ #include "stdio.h" #include "string.h" struct node { int l,r,x;// 在叶子节点代表值,树节点代表成端更新的lazy操作. }data[400010]

hdu 4288 线段树

没看懂先mark 题意: 维护一个有序数列{An},有三种操作: 1.添加一个元素. 2.删除一个元素. 3.求数列中下标%5 = 3的值的和. 解题思路: 看的各种题解,今天终于弄懂了. 由于线段树中不支持添加.删除操作,所以题解写的是用离线做法. 我们来看它是如何解决添加.删除的问题的. 首先将所有出现过的数记录下来,然后排序去重,最后根据去重结果建树,然后每个操作数都会对应线段树中的一个点. 遇到添加.删除操作的时候,只要把那个节点的值改变,然后将它对下标的影响处理好就可以. 那么如何处理

hdu 4288 线段树 + 离散化

题意:求一个动态的非递减序列中,下标 mod 5 == 3的元素和,可以向序列中添加和删除某些元素,且序列的单调性不变.保证在任意时间 序列中不会存在两个相同元素.保证输入合法 思路:保证在任意时间 序列中不会存在两个相同元素,也就说明如果将所有的值都插入序列中,每个值对应的位置是唯一的.所以将操作的值先保存下来,离散化处理出每个值对应的位置.离散化后,我们得到一个新的数列 uni_num[] .通过题意的描述,我们可以发现一个性质,每当我们在 i 位置插入或者删除一个 uni_num[k] 时

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

http://acm.hdu.edu.cn/showproblem.php?pid=4288 开始的时候,果断TLE,做的方法是,线段树上仅仅维护%5==3的坐标,比如1 2 3 4 5 6 7  如果删除第三个数,就将3,6的位置全+1,就是向右偏移以为,但是求和还是很慢,所以即使10秒,还是TLE... 正确做法: 1.节点内维护sum[0...4]分别代表区间内%5==i的和 2.结点维护点的个数,cnt 3.离散化处理,然后每次插入时,经过的结点cnt+1或-1,叶子节点Sum[0]就是

HDU 4893 Wow! Such Sequence 线段树暴力

题意:n个数 初始为0,三个操作:给某个数加上d,查询区间和,把区间[l,r]中每个a[i]变为离a[i]最近的斐波那契数,n,m<=1e5. 无操作1情况下,每个点最多变化一次,每次修改logn,算上操作1 最坏情况下修改n+m次 O((n+m)logn). 对区间设个标记 线段树暴力即可. #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const int

HDU 4893 线段树裸题

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2512    Accepted Submission(s): 751 Problem Description Recently, Doge got a funny birthday present from his new friend, Pro

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw

hdu 4893 线段树 --- 也是两个变 类似双标记

http://acm.hdu.edu.cn/showproblem.php?pid=4893 开始的时候,我按双标记,WA了一下午,搞不定,我是用的两个标记add--表示当前结点中有值发生变化,flag,斐波那契的懒惰标记,但是估计是我自己处理的有问题,一直不对 参考了别人的代码,写法还是很不错的,Add变量维护的是,完全变成Fibonacci的时候的和,---回头我再重新写一遍 #include <cstdio> #include <cstring> #include <a

HDU 4302 线段树单点更新,维护区间最大最小值

http://acm.hdu.edu.cn/showproblem.php?pid=4302 Problem Description Holedox is a small animal which can be considered as one point. It lives in a straight pipe whose length is L. Holedox can only move along the pipe. Cakes may appear anywhere in the p