• 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("*****
    ");
    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
    ",sum);
    55             }
    56         }
    57     }
    58 }
    View Code
     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("*****
    ");
    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
    ",sum[1][3]);
    72         }
    73     }
    74     return 0;
    75 }
  • 相关阅读:
    centos : 创建交换分区
    用法记录
    mysql日志清理
    mysql 通过查看mysql 配置参数、状态来优化你的mysql
    [WPF 自定义控件]Window(窗体)的UI元素及行为
    [WPF 自定义控件]为Form和自定义Window添加FunctionBar
    [WPF 自定义控件]让Form在加载后自动获得焦点
    [WPF 自定义控件]简单的表单布局控件
    [WPF 自定义控件]以Button为例谈谈如何模仿Aero2主题
    [WPF 自定义控件]自定义控件的代码如何与ControlTemplate交互
  • 原文地址:https://www.cnblogs.com/cnblogs321114287/p/4356512.html
Copyright © 2020-2023  润新知