2325: [ZJOI2011]道馆之战

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 813  Solved: 309
[Submit][Status]

Description

口袋妖怪(又名神奇宝贝或宠物小精灵)//绿宝石中的水系道馆需要经过三个冰地才能到达馆主的面前,冰地中的每一个冰块都只能经过一次。当一个冰地上的所有冰块都被经过之后,到下一个冰地的楼梯才会被打开。

三个冰地分别如下:

 

当走出第三个冰地之后,就可以与馆主进行道馆战了。

馆主发现这个难度太小,导致经常有挑战者能通过,为了加大难度,将道馆分成了n个房间,每个房间中是两个冰块或障碍,表示一列冰地。任意两个房间之间均有且仅有一条路径相连,即这n个房间构成一个树状结构。

每个房间分成了A和B两个区域,每一区域都是一个薄冰块或者障碍物。每次只能移动到相邻房间的同一类区域(即若你现在在这个房间的A区域,那么你只能移动到相邻房间的A区域)或这个房间的另一区域。

现在挑战者从房间u出发,馆主在房间v,那么挑战者只能朝接近馆主所在房间的方向过去。一开始挑战者可以在房间u的任意一个冰块区域内。如果挑战者踩过的冰块数达到了最大值(即没有一种方案踩过的冰块数更多了),那么当挑战者走到最后一个冰块上时,他会被瞬间传送到馆主面前与馆主进行道馆战。

自从馆主修改规则后已经经过了m天,每天要么是有一个挑战者来进行挑战,要么就是馆主将某个房间进行了修改。对于每个来的挑战者,你需要计算出他若要和馆主进行战斗需要经过的冰块数。

 

Input

第一行包含两个正整数n和m。

2行到第n行,每行包含两个正整数x和y,表示一条连接房间x和房间y的边。房间编号为1…n。

接下来n行,每行包含两个字符。第n + k行表示房间k的两个区域,第一个字符为A区域,第二个字符为B区域。其中“.”(ASCII码为46)表示是薄冰块,“#(ASCII码为35)表示是障碍物。

最后的m行,每行一个操作:

l C u s:将房间u里的两个区域修改为s。

l Q u v:询问挑战者在房间u,馆主在房间v时,挑战者能与馆主进行挑战需要踩的冰块数。如果房间u的两个区域都是障碍物,那么输出0

Output

 包含若干行,每行一个整数。即对于输入中的每个询问,依次输出一个答案。

Sample Input

5 3

1 2

2 3

2 4

1 5

.#

..

#.

.#

..

Q 5 3

C 1 ##

Q 4 5

Sample Output

6

3

HINT

【样例说明】


第一个询问,从房间5出发经过的冰块数最多的路径为:

第二个询问,从房间4出发经过的冰块数最多的路径为:


【数据规模】




 N≤ 30 000



M ≤ 80 000



Source

Day2

 

题目描述太蛋疼了……

总结一下就是一棵树上,每个点有a,b两个值,空地或者障碍,障碍就不能通过,同一个节点中a可以到b,但是a是障碍或者b是障碍就不行

询问从x到y,x从(a,b)两个点其中一个出发,最多能走多少个空地。即不要求能到达y,只求最多能走多少步

看了人家的题解,x[0..1][0..1]表示从左边的 左/右上角到 右边的 左/右上角 最多走多少步,即要求必须到达要走多少步

l[0..1]表示从左边 左/右上角出发能走多少步,r[0..1]同理

看update函数吧,不是特别麻烦,但是要注意细节

另外在树链剖分算答案的时候,由于你每条线段都是由根往下的

但x到y,从x到lca的路径是从下往上,lca到y的路径是从上往下,

也就是说求出的x到lca的路径,要反向!!!!!

妈的我只swap了l[0],r[0]和l[1]和r[1]

妈的还要swap x[0][1] 和x[1][0]啊啊啊啊啊啊!!!!调了一个半小时艹

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
/*
Author:wuhuajun
*/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define lson l, mid, rt << 1
#define rson mid+1, r, rt << 1 | 1
using namespace std;
  
typedef long long ll;
typedef double dd;
const int maxn=100010, INF = 1000000007;
  
int edge, n, fa[maxn], sz[maxn], son[maxn], dep[maxn], hash[maxn], top[maxn];
int h[maxn], num, a[maxn], x, y, tx, ty, Q, b[maxn];
char s[22], s1[22], s2[22];
  
struct Edge
{
    int to, ne;
} e[maxn * 2];
  
struct Seg
{
    int x[2][2], l[2], r[2];
    void clear()
    {
        x[0][0] = x[0][1] = x[1][0] = x[1][1] = 0;
        l[0] = l[1] = r[0] = r[1] = 0;
    }
} seg[maxn << 2], ans, c, L, R, ret;
  
void close()
{
    exit(0);
}
  
void addedge(int x,int y)
{
    e[edge].to = y;
    e[edge].ne = h[x];
    h[x] = edge++;
}
  
void dfs(int k,int from)
{
    sz[k] = 1;
    son[k] = 0;
    dep[k] = dep[from] + 1;
    for (int p=h[k];p!=-1;p=e[p].ne)
    {
        int to = e[p].to;
        if (from == to) continue;
        fa[to] = k;
        dfs(to, k);
        sz[k] += sz[to];
        if (sz[to] > sz[son[k]]) son[k] = to;
    }
}
  
void build(int k,int from)
{
    hash[k] = ++num;
    top[k] = from;
    if (son[k]) build(son[k], from);
    for (int p=h[k];p!=-1;p=e[p].ne)
    {
        int to = e[p].to;
        if (to != fa[k] && to != son[k])
            build(to, to);
    }
}
  
//{{{Segment部分
  
int cal(int x,int y)
{
    return max(-INF, max(x, y));
}
  
Seg operator + (Seg a,Seg b)
{
    if (a.x[0][0] == 0 && a.x[0][1] == 0 && a.x[1][0] == 0 && a.x[1][1] == 0 && a.l[0] == 0 && a.l[1] == 0 && a.r[0] == 0 && a.r[1] == 0)
        return b;
    if (b.x[0][0] == 0 && b.x[0][1] == 0 && b.x[1][0] == 0 && b.x[1][1] == 0 && b.l[0] == 0 && b.l[1] == 0 && b.r[0] == 0 && b.r[1] == 0)
        return a;
    c.x[0][0] = cal(a.x[0][0] + b.x[0][0], a.x[0][1] + b.x[1][0]);
    c.x[0][1] = cal(a.x[0][0] + b.x[0][1], a.x[0][1] + b.x[1][1]);
    c.x[1][0] = cal(a.x[1][0] + b.x[0][0], a.x[1][1] + b.x[1][0]);
    c.x[1][1] = cal(a.x[1][0] + b.x[0][1], a.x[1][1] + b.x[1][1]);
    c.l[0] = max(a.l[0], max(a.x[0][0] + b.l[0], a.x[0][1] + b.l[1]));
    c.l[1] = max(a.l[1], max(a.x[1][0] + b.l[0], a.x[1][1] + b.l[1]));
    c.r[0] = max(b.r[0], max(b.x[0][0] + a.r[0], b.x[1][0] + a.r[1]));
    c.r[1] = max(b.r[1], max(b.x[0][1] + a.r[0], b.x[1][1] + a.r[1]));
    return c;
}
  
void change(int L,int R,int val1,int val2,int l,int r,int rt)
{
    if (L <= l && r <= R)
    {
        seg[rt].x[0][0] = seg[rt].l[0] = seg[rt].r[0] = val1;
        seg[rt].x[1][1] = seg[rt].l[1] = seg[rt].r[1] = val2;
        if (val1 == 1 && val2 == 1)
        {
            seg[rt].l[0] = seg[rt].l[1] = seg[rt].r[0] = seg[rt].r[1] = 2;
            seg[rt].x[0][1] = seg[rt].x[1][0] = 2;
        }
        else
        {
            seg[rt].x[0][1] = seg[rt].x[1][0] = -INF;
        }
        seg[rt].l[0] = max(seg[rt].l[0], 0);
        seg[rt].l[1] = max(seg[rt].l[1], 0);
        seg[rt].r[0] = max(seg[rt].r[0], 0);
        seg[rt].r[1] = max(seg[rt].r[1], 0);
        return;
    }
    int mid = (l + r) >> 1;
    if (L <= mid)
        change(L,R,val1,val2,lson);
    if (mid + 1 <= R)
        change(L,R,val1,val2,rson);
    seg[rt] = seg[rt << 1] + seg[rt << 1 | 1];
}
  
Seg query(int L,int R,int l,int r,int rt)
{
    if (L <= l && r <= R)
    {
        return seg[rt];
    }
    int mid = (l + r) >> 1;
    Seg ans;
    ans.clear();
    if (L <= mid)
        ans = ans + query(L,R,lson);
    if (mid + 1 <= R)
        ans = ans + query(L,R,rson);
    return ans;
}
//}}}
  
Seg get_ans()
{
    tx = top[x];
    ty = top[y];
    L.clear();
    R.clear();
    while (tx != ty)
    {
        if (dep[tx] < dep[ty])
        {
            R = query(hash[ty], hash[y], 1, n, 1) + R;
            y = fa[ty];
            ty = top[y];
        }
        else
        {
            L = query(hash[tx], hash[x], 1, n, 1) + L;
            x = fa[tx];
            tx = top[x];
        }
    }
    if (dep[x] < dep[y])
    {
        R = query(hash[x], hash[y], 1, n, 1) + R;
    }
    else
    {
        L = query(hash[y], hash[x], 1, n, 1) + L;
    }
    swap(L.x[0][1], L.x[1][0]);
    swap(L.l[0], L.r[0]);
    swap(L.l[1], L.r[1]);
    return L + R;
}
  
void init()
{
    scanf("%d %d",&n,&Q);
    memset(h,-1,sizeof(h));
    for (int i=1;i<=n-1;i++)
    {
        scanf("%d %d",&x, &y);
        addedge(x, y);
        addedge(y, x);
    }
    for (int i=1;i<=n;i++)
    {
        scanf("%s", s1);
        a[i] = s1[0] == '.' ? 1 : -INF;
        b[i] = s1[1] == '.' ? 1 : -INF;
    }
    dfs(1, 0);
    build(1, 1);
    /*
    for (int i=1;i<=n;i++)
    {
        printf("i:%d top:%d hash:%d\n",i, top[i], hash[i]);
    }
    */
    for (int i=1;i<=n;i++)
        change(hash[i], hash[i], a[i], b[i], 1, n, 1);
    while (Q--)
    {
        scanf("%s", s);
        if (s[0] == 'Q')
        {
            scanf("%d %d",&x, &y);
            ret = get_ans();
            printf("%d\n", max(ret.l[0], ret.l[1]));
        }
        else
        {
            scanf("%d",&x);
            scanf("%s", s1);
            int t1 = s1[0] == '.' ? 1 : -INF;
            int t2 = s1[1] == '.' ? 1 : -INF;
            change(hash[x], hash[x], t1, t2, 1, n, 1);
        }
    }
}
  
int main ()
{
    init();
    close();
    return 0;
}

 

posted on   cssystem  阅读(440)  评论(0编辑  收藏  举报
努力加载评论中...

点击右上角即可分享
微信分享提示