BZOJ 3110 树套树 && 永久化标记

感觉树套树是个非常高深的数据结构。从来没写过

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <vector>
  6 #define LL long long
  7 using namespace std;
  8 const LL Maxm=50100;
  9 const LL Maxn=50100;
 10 const LL T=300;
 11 struct OPERATOR
 12 {
 13     LL Type,a,b,c;
 14 }Operator[Maxm];
 15 LL Sum[Maxn*T],ls[Maxn*T],rs[Maxn*T],Addv[Maxn*T],sz=0,V[Maxm],Root[Maxn*6];
 16 LL n,m,H;
 17 inline void Get_Int(LL &x)
 18 {
 19     x=0; register char ch=getchar(); LL f=1;
 20     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
 21     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} x*=f;
 22 }
 23 inline void Put_Int(LL x)
 24 {
 25     char ch[20]; register int top=0;
 26     if (x==0) ch[++top]='0';
 27     while (x) ch[++top]=x%10+'0',x/=10;
 28     while (top) putchar(ch[top--]); putchar('
');
 29 }
 30 //=================================================================
 31 inline void Push_Down(LL o,LL p,LL q)
 32 {
 33     if (!ls[o]) ls[o]=++sz;
 34     if (!rs[o]) rs[o]=++sz;
 35     LL l=ls[o],r=rs[o];
 36     if (Addv[o])
 37     {
 38         Addv[l]+=Addv[o];
 39         Addv[r]+=Addv[o];
 40         LL mid=(p+q)>>1;
 41         Sum[l]+=(mid-p+1)*Addv[o];
 42         Sum[r]+=(q-mid)*Addv[o];
 43         Addv[o]=0;
 44     }
 45 }
 46 inline void Push_Up(LL o) {Sum[o]=Sum[ls[o]]+Sum[rs[o]];}
 47 void Add_Num(LL &o,LL l,LL r,LL p,LL q)
 48 {
 49     if (o==0) o=++sz;
 50     if (l==p && r==q)
 51     {
 52         Sum[o]+=(q-p+1);
 53         Addv[o]++;
 54         return;
 55     }
 56     Push_Down(o,l,r);
 57     LL mid=(l+r)>>1;
 58     if (q<=mid) Add_Num(ls[o],l,mid,p,q);
 59     if (p>=mid+1) Add_Num(rs[o],mid+1,r,p,q);
 60     if (p<=mid && q>=mid+1) 
 61         Add_Num(ls[o],l,mid,p,mid),Add_Num(rs[o],mid+1,r,mid+1,q);
 62     Push_Up(o);
 63 }
 64 void Update(LL o,LL l,LL r,LL p,LL q,LL c)
 65 {
 66     Add_Num(Root[o],1,n,p,q);
 67     if (l==r) return;
 68     LL mid=(l+r)>>1;
 69     if (c<=mid) Update(o<<1,l,mid,p,q,c); 
 70     if (c>=mid+1) Update(o<<1|1,mid+1,r,p,q,c);
 71 }
 72 //========================================
 73  
 74 LL Get_Sum(LL o,LL l,LL r,LL p,LL q)
 75 {
 76     if (!o) return 0;
 77     if (p==l && r==q) return Sum[o];
 78     LL mid=(l+r)>>1;
 79     Push_Down(o,l,r);
 80     if (q<=mid) return Get_Sum(ls[o],l,mid,p,q);
 81     if (p>=mid+1) return Get_Sum(rs[o],mid+1,r,p,q);
 82     if (p<=mid && q>=mid+1) return Get_Sum(ls[o],l,mid,p,mid)+Get_Sum(rs[o],mid+1,r,mid+1,q);
 83 }
 84  
 85  
 86 LL Query(LL o,LL l,LL r,LL p,LL q,LL k)
 87 {
 88     LL ret=Get_Sum(Root[o<<1],1,n,p,q);
 89     if (l==r) return l;
 90     LL mid=(l+r)>>1;
 91     if (k<=ret) return Query(o<<1,l,mid,p,q,k);
 92     if (k>=ret+1) return Query(o<<1|1,mid+1,r,p,q,k-ret);
 93 }
 94  
 95 int main()
 96 {
 97     Get_Int(n),Get_Int(m);  LL cnt=0;
 98     for (int i=1;i<=m;i++)
 99     {
100         Get_Int(Operator[i].Type);
101         Get_Int(Operator[i].a),Get_Int(Operator[i].b),Get_Int(Operator[i].c);
102         if (Operator[i].Type==1) V[++cnt]=Operator[i].c;
103     }
104     sort(V+1,V+cnt+1); 
105     H=unique(V+1,V+cnt+1)-(V+1);
106     for (int i=1;i<=m;i++)
107     {
108         if (Operator[i].Type==1) Update(1,1,H,Operator[i].a,Operator[i].b,H-(lower_bound(V+1,V+H+1,Operator[i].c)-V)+1);
109         if (Operator[i].Type==2) Put_Int(V[H-Query(1,1,H,Operator[i].a,Operator[i].b,Operator[i].c)+1]);
110     }
111     return 0;
112 }
C++

加了标记永久化以后

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <vector>
 6 #define LL long long
 7 using namespace std;
 8 const LL Maxm=50100;
 9 const LL Maxn=50100;
10 const LL T=300;
11 struct OPERATOR
12 {
13     LL Type,a,b,c;
14 }Operator[Maxm];
15 LL Sum[Maxn*T],ls[Maxn*T],rs[Maxn*T],Addv[Maxn*T],sz=0,V[Maxm],Root[Maxn*6];
16 LL n,m,H;
17 inline void Get_Int(LL &x)
18 {
19     x=0; register char ch=getchar(); LL f=1;
20     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
21     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} x*=f;
22 }
23 inline void Put_Int(LL x)
24 {
25     char ch[20]; register int top=0;
26     if (x==0) ch[++top]='0';
27     while (x) ch[++top]=x%10+'0',x/=10;
28     while (top) putchar(ch[top--]); putchar('
');
29 }
30 //=================================================================
31 void Add_Num(LL &o,LL l,LL r,LL p,LL q)
32 {
33     if (o==0) o=++sz;
34     Sum[o]+=(q-p+1);
35     if (l==p && r==q)
36     {
37         Addv[o]++;
38         return;
39     }
40     if (!ls[o]) ls[o]=++sz;
41     if (!rs[o]) rs[o]=++sz;
42     LL mid=(l+r)>>1;
43     if (q<=mid) Add_Num(ls[o],l,mid,p,q);
44     if (p>=mid+1) Add_Num(rs[o],mid+1,r,p,q);
45     if (p<=mid && q>=mid+1) 
46         Add_Num(ls[o],l,mid,p,mid),Add_Num(rs[o],mid+1,r,mid+1,q);
47 }
48 void Update(LL o,LL l,LL r,LL p,LL q,LL c)
49 {
50     Add_Num(Root[o],1,n,p,q);
51     if (l==r) return;
52     LL mid=(l+r)>>1;
53     if (c<=mid) Update(o<<1,l,mid,p,q,c); 
54     if (c>=mid+1) Update(o<<1|1,mid+1,r,p,q,c);
55 }
56 //========================================
57   
58 LL Get_Sum(LL o,LL l,LL r,LL p,LL q,LL pos)
59 {
60     if (!o) return 0;
61     if (p==l && r==q) return Sum[o]+pos*(r-l+1);
62     LL mid=(l+r)>>1;
63     if (!ls[o]) ls[o]=++sz;
64     if (!rs[o]) rs[o]=++sz;
65     if (q<=mid) return Get_Sum(ls[o],l,mid,p,q,pos+Addv[o]);
66     if (p>=mid+1) return Get_Sum(rs[o],mid+1,r,p,q,pos+Addv[o]);
67     if (p<=mid && q>=mid+1) return Get_Sum(ls[o],l,mid,p,mid,pos+Addv[o])+Get_Sum(rs[o],mid+1,r,mid+1,q,pos+Addv[o]);
68 }
69   
70   
71 LL Query(LL o,LL l,LL r,LL p,LL q,LL k)
72 {
73     LL ret=Get_Sum(Root[o<<1],1,n,p,q,0);
74     if (l==r) return l;
75     LL mid=(l+r)>>1;
76     if (k<=ret) return Query(o<<1,l,mid,p,q,k);
77     if (k>=ret+1) return Query(o<<1|1,mid+1,r,p,q,k-ret);
78 }
79   
80 int main()
81 {
82     // freopen("sequence.in","r",stdin);
83     // freopen("sequence.out","w",stdout);
84     Get_Int(n),Get_Int(m);  LL cnt=0;
85     for (int i=1;i<=m;i++)
86     {
87         Get_Int(Operator[i].Type);
88         Get_Int(Operator[i].a),Get_Int(Operator[i].b),Get_Int(Operator[i].c);
89         if (Operator[i].Type==1) V[++cnt]=Operator[i].c;
90     }
91     sort(V+1,V+cnt+1); 
92     H=unique(V+1,V+cnt+1)-(V+1);
93     for (int i=1;i<=m;i++)
94     {
95         if (Operator[i].Type==1) Update(1,1,H,Operator[i].a,Operator[i].b,H-(lower_bound(V+1,V+H+1,Operator[i].c)-V)+1);
96         if (Operator[i].Type==2) Put_Int(V[H-Query(1,1,H,Operator[i].a,Operator[i].b,Operator[i].c)+1]);
97     }
98     return 0;
99 }
C++

直接20s卡时,加了标记永久化之后18s,还是很慢!

原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5509204.html