码迷,mamicode.com
首页 > 其他好文 > 详细

Weed(线段树)

时间:2019-08-10 19:30:50      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:tchar   eve   dom   ++   随机   直接   and   event   平衡树   

考试只好随便骗骗分过去啦啦啦.....

 

正解是玄学线段树:

以每个操作为叶子节点,我们定义几个变量ce表示层数,h表示高度,add表示所减的层数

那么问题转化为单点修改的问题输出直接是根节点答案

但是我们发现合并区间很毒瘤

我们分两种情况:

设L为左儿子,R为右儿子。

1.T[L].ce<T[R].add 显然我们只需O(1)修改。

2.T[L].ce>T[R].add 我们需要将左子树后面的add个减去,我们自然想到了类似平衡树的

查找后缀的操作,于是肝.....

开始时我的query计算有多少减去,但是WA20

因为少考虑一种情况:

你的左子树中假设左子树根结点为K,左儿子Lson,右儿子Rson

右儿子中也可能有剩余的add,

那么我们直接发现右面不够查左面是不行的.........

听了toot大神的建议,我改为了查询还有多少留下

 

     if(t[k*2+1].ce<ceng)
     {
          qq_sum+=t[k*2+1].h;
          query_sum(k*2,l,mid,ceng-t[k*2+1].ce+t[k*2+1].add);
     }

 

当发现右端点少时,向左端点转移还需要减去靠右的add个

然后就没啥了,注意细节就好

技术图片
  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<set>
  6 #include<map>
  7 #define int long long
  8 #define MAXN 1000010
  9 using namespace std;
 10 int read()
 11 {
 12     int x=0;char c=getchar();
 13     while(c<0||c>9)c=getchar();
 14     while(c>=0&&c<=9)
 15     {
 16          x=(x<<1)+(x<<3)+(c^48);
 17          c=getchar();
 18     }
 19     return x;
 20 }
 21 struct node{int ce,h,add,l,r;}t[MAXN*2];
 22 int qq_sum;int m,q;
 23 int orz[MAXN],mm[MAXN];
 24 void query_sum(int k,int l,int r,int ceng)
 25 {
 26      if(l==r)
 27      {
 28         if(ceng!=0)qq_sum+=t[k].h;
 29         return ;
 30      }
 31      int mid=(l+r)>>1;
 32      //printf("k=%lld l=%lld r=%lld\n",k,l,r);
 33      if(t[k*2+1].ce<ceng)
 34      {
 35           qq_sum+=t[k*2+1].h;
 36           query_sum(k*2,l,mid,ceng-t[k*2+1].ce+t[k*2+1].add);
 37      }
 38      else
 39      {
 40           query_sum(k*2+1,mid+1,r,ceng);
 41      }
 42      return ;
 43 }
 44 void updata(int k)//左儿子是否保存
 45 {
 46      int r=k*2+1;
 47      int l=k*2;
 48      //printf("--------\nupdata k=%lld %lld %lld\n",k,l,r);
 49 //     t[k].ce=t[l].ce+t[r].ce;
 50 //     t[k].h=t[l].h+t[r].h;
 51 //     t[k].add=t[l].add+t[r].add;
 52      if(t[l].ce>t[r].add)
 53      {
 54          t[k].ce=t[l].ce+t[r].ce-t[r].add;
 55          qq_sum=0;
 56          query_sum(l,t[l].l,t[l].r,t[r].add); 
 57          t[k].h=t[l].h+t[r].h-qq_sum;
 58          t[k].add=t[l].add;
 59          //printf("--t[k].ce=%lld t[k].h=%lld add=%lld\n",t[k].ce,t[k].h,t[k].add);
 60      }
 61      else
 62      {
 63          t[k].h=t[r].h;
 64          t[k].ce=t[r].ce;
 65          t[k].add=t[r].add+t[l].add-t[l].ce;
 66          //printf("t[k].ce=%lld t[k].h=%lld add=%lld\n",t[k].ce,t[k].h,t[k].add);      
 67      }
 68      //printf("-----------\n");
 69      return ;
 70 }
 71 void build(int k,int l,int r)
 72 {
 73      t[k].l=l;t[k].r=r;
 74      if(l==r)
 75      {
 76         orz[l]=read();mm[l]=read();
 77         if(orz[l]==0)
 78         {
 79             t[k].ce=1;t[k].h=mm[l];
 80             //printf("t[%lld].ce=%lld t[%lld].h=%lld\n",k,t[k].ce,k,t[k].h);           
 81         }
 82         else
 83         {
 84             t[k].add=mm[l];
 85             //printf("t[%lld].add=%lld\n",k,t[k].add);           
 86         }
 87         return ;
 88      }
 89      int mid=(l+r)>>1;
 90      build(k*2,l,mid);
 91      build(k*2+1,mid+1,r);
 92      updata(k);     
 93 }
 94 void F_add(int k,int l,int orzz,int x)
 95 {
 96      if(t[k].l==t[k].r)
 97      {
 98           t[k].add=0;t[k].ce=0;t[k].h=0;
 99           if(orzz==0)
100           {
101               t[k].ce=1;
102               t[k].h=x;
103               //printf("t[%lld].ce=%lld t[%lld].h=%lld\n",k,t[k].ce,k,t[k].h);
104           }
105           else
106           {
107               t[k].add=x;
108               //printf("t[%lld].add=%lld\n",k,t[k].add);
109           }
110           return ;
111      }
112      int mid=(t[k].l+t[k].r)>>1;
113      if(l<=mid)F_add(k*2,l,orzz,x);
114      else F_add(k*2+1,l,orzz,x);
115      updata(k);
116 }
117 signed main()
118 {
119     //freopen("text.in","r",stdin);
120    // freopen("kkk.out","w",stdout);
121     m=read();q=read();
122     //printf("build\n");
123     build(1ll,1ll,m);
124     //printf("t[1].h=%lld\n",t[1ll].h);
125     for(int i=1;i<=q;++i)
126     {
127         int x,y,z;
128         x=read();y=read();z=read();
129         F_add(1,x,y,z);
130         printf("%lld\n",t[1].h);
131     }
132 }
View Code

 

附上对拍

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 { 
 5     int c=0;
 6     while(true)
 7     {
 8          system("./pai");//puts("ran work out");
 9          system("./b");//puts("ac work out");
10          system("./kkk");//puts("kx work out");
11          if(system("diff -b -B b.out kkk.out"))
12          {
13             puts("WA");
14             return 0;
15          }
16          cout<<++c<<" ";
17          puts("AC");
18     }
19     return 0;
20 }
21 /*
22 g++ pai.cpp -o pai 
23 ./pai
24 g++ b.cpp -o b
25 ./b
26 g++ kkk.cpp -o kkk
27 ./kkk
28 g++ ran.cpp -o ran
29 ./ran
30 */
View Code

随机数据生成

技术图片
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int random(int m)
 4 {
 5     return (long long)rand()*rand()%m;
 6 }
 7 int judge()
 8 {
 9    int x=rand();
10    if(x%2)return 1;
11    else return 0;
12 }
13 pair<int,int>e[100000];
14 map<pair<int,int>,bool>h;
15 int main()
16 {
17     freopen("text.in","w",stdout);
18     srand((unsigned)time(0));
19     int n=random(7)+1;
20     int m=10;
21     int q=10;
22     printf("%d %d\n",m,q);
23     for(int i=1;i<=m;++i)
24     {
25         printf("%d %d\n",judge(),random(10)+1);
26     }
27     for(int i=1;i<=q;++i)
28     {
29         printf("%d %d %d\n",random(m)+1,judge(),random(10)+1);
30     }
31     return 0;
32 }
View Code

 

Weed(线段树)

标签:tchar   eve   dom   ++   随机   直接   and   event   平衡树   

原文地址:https://www.cnblogs.com/Wwb123/p/11332356.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!