洛谷 P3437 [POI2006]TET-Tetris 3D

二维线段树区间更新啊

树套树的外层树,如果是线段树的话一般似乎不能打标记?(毕竟标记不好下传)

然而起码对于这题是可以的...对于外层线段树,每个节点放两个内层线段树dat和setv,分别是得到的值和修改操作留下的标记。

然后外层线段树要标记永久化...标记永久化之后,标记的定义不一样了。

这道题里用dat[i]表示i节点表示的整段区间都达到的值,setv[i]表示i节点表示的区间的最大值

(这两个的名字似乎反了?)

这样进行修改操作的时候,更新所有经过的节点的setv(因为只要经过该点,那么该点表示的区间和目标区间一定有相交部分),更新被目标区间完全包含的区间所在节点的dat(自然整段都达到那个值了)

进行查询操作的时候,"所有经过节点的dat"和"所有被目标区间完全包含的区间所在节点的setv"的最大值就是答案。

二维都一样,只不过外层线段树的查询是对于内层线段树的给定区间查询/修改

标记不下传

(一眼看起来似乎不是很对?有些信息被遗漏了?然而的确是对的23333)

(似乎修改和查询完全是对称的...)

错误记录:71行少了分号后的两个语句导致WA一片

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #define lc (num<<1)
 5 #define rc (num<<1|1)
 6 #define mid ((l+r)>>1)
 7 using namespace std;
 8 int n,m;
 9 namespace XXX
10 {
11     int L,R,x;
12 struct Y
13 {
14     int dat[2100],setv[2100];
15     //dat表示整段区间都达到的值,setv表示区间最大值
16     void update(int l,int r,int num)
17     {
18         setv[num]=max(setv[num],x);
19         if(L<=l&&r<=R)
20         {
21             dat[num]=max(dat[num],x);
22             return;
23         }
24         if(L<=mid)    update(l,mid,lc);
25         if(mid<R)    update(mid+1,r,rc);
26     }
27     int query(int l,int r,int num)
28     {
29         if(L<=l&&r<=R)    return setv[num];
30         int ans=dat[num];
31         if(L<=mid)    ans=max(ans,query(l,mid,lc));
32         if(mid<R)    ans=max(ans,query(mid+1,r,rc));
33         return ans;
34     }
35 };
36 }
37 int L,R,x;
38 XXX::Y dat[2100],setv[2100];
39 void update(int l,int r,int num)
40 {
41     XXX::x=x;
42     setv[num].update(1,m,1);
43     if(L<=l&&r<=R)
44     {
45         XXX::x=x;
46         dat[num].update(1,m,1);
47         return;
48     }
49     if(L<=mid)    update(l,mid,lc);
50     if(mid<R)    update(mid+1,r,rc);
51 }
52 int query(int l,int r,int num)
53 {
54     if(L<=l&&r<=R)    return setv[num].query(1,m,1);
55     int ans=dat[num].query(1,m,1);
56     if(L<=mid)    ans=max(ans,query(l,mid,lc));
57     if(mid<R)    ans=max(ans,query(mid+1,r,rc));
58     return ans;
59 }
60 int main()
61 {
62     int Q,d,s,w,xx,yy;
63     scanf("%d%d%d",&n,&m,&Q);
64     while(Q--)
65     {
66         scanf("%d%d%d%d%d",&d,&s,&w,&xx,&yy);xx++;yy++;
67         L=xx;R=xx+d-1;XXX::L=yy;XXX::R=yy+s-1;
68         x=query(1,n,1)+w;//printf("%d\n",x);
69         update(1,n,1);
70     }
71     L=1;R=n;XXX::L=1;XXX::R=m;
72     printf("%d",query(1,n,1));
73     return 0;
74 }
posted @ 2018-03-17 18:01  hehe_54321  阅读(564)  评论(0编辑  收藏  举报
AmazingCounters.com