您的位置:首页 > 其它

bzoj1018 [SHOI2008]堵塞的交通traffic

2015-07-02 21:41 603 查看

1018: [SHOI2008]堵塞的交通traffic

Time Limit: 3 Sec Memory Limit: 162 MB
Submit: 2208 Solved: 687
[Submit][Status][Discuss]

Description

有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个城市和3C-2条道路。 小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式: Close r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被堵塞了; Open r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被疏通了; Ask r1 c1 r2 c2:询问城市(r1,c1)和(r2,c2)是否连通。如果存在一条路径使得这两条城市连通,则返回Y,否则返回N;

Input

第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为结束。我们假设在一开始所有的道路都是堵塞的。 对30%测试数据,我们保证C小于等于1000,信息条数小于等于1000; 对100%测试数据,我们保证 C小于等于100000,信息条数小于等于100000。

Output

对于每个查询,输出一个“Y”或“N”。

Sample Input

2

Open 1 1 1 2

Open 1 2 2 2

Ask 1 1 2 2

Ask 2 1 2 2

Exit

Sample Output

Y

N

HINT

Source

题意:显然

分析:这题的思路是很容易想到的,可以用线段树来维护某一段四个端点之间的连通性,维护是显然的

但是,有可能出现这种恶心情况

1-2-3

| | |

4-5-6

T_T

无泪哭

所以需要4*4的矩阵维护四个端点之间的连通性,

所以更新是很容易的

但是询问就要这样了

首先假设询问(Lx, Rx)这段区间的连通性

那么先查询1-Lx的连通性,先知晓第Lx列的连通性

然后查询Rx-n的连通性,知晓第Rx列的连通性

然后查询Lx-Rx的连通性,用这三块东西并起来求答案

这样就可以了

综上所述,本题得解

T_T

我的代码不知为何RE

太坑了

。。。。。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <deque>
#include <vector>
#include <queue>
#include <iostream>
#include <algorithm>
#include <map>
#include <set>
#include <ctime>
using namespace std;
typedef long long LL;
#define For(i, s, t) for(int i = (s); i <= (t); i++)
#define Ford(i, s, t) for(int i = (s); i >= (t); i--)
#define Rep(i, t) for(int i = (0); i < (t); i++)
#define Repn(i, t) for(int i = ((t)-1); i >= (0); i--)
#define MIT (2147483647)
#define INF (1000000001)
#define MLL (1000000000000000001LL)
#define sz(x) ((bnt) (x).size())
#define clr(x, y) memset(x, y, sizeof(x))
#define puf push_front
#define pub push_back
#define pof pop_front
#define pob pop_back
#define ft first
#define sd second
#define mk make_pair
inline void SetIO(string Name) {
string Input = Name+".in",
Output = Name+".out";
freopen(Input.c_str(), "r", stdin),
freopen(Output.c_str(), "w", stdout);
}

const int N = 100010;
struct State {
bool Connect[4][4];

State() {
clr(Connect, 0);
}

inline void Gone() {
Rep(k, 4)
Rep(i, 4)
Rep(j, 4) Connect[i][j] |= Connect[i][k]&Connect[k][j];
}

inline void Add(State &A) {
Rep(i, 4)
Rep(j, 4) Connect[i][j] |= A.Connect[i][j];
}

inline void Check() {
Rep(i, 4)
Rep(j, 4) Connect[i][j] |= Connect[j][i];
}

inline State operator +(State B) {
State Ret, A;
Rep(i, 4)
Rep(j, 4) A.Connect[i][j] = Connect[i][j];
Rep(i, 2)
Rep(j, 2) {
bool T = A.Connect[i+2][j+2]|B.Connect[i][j];
A.Connect[i+2][j+2] |= T, B.Connect[i][j] |= T;
}
A.Check(), B.Check();
A.Gone(), B.Gone();

Rep(i, 4) Ret.Connect[i][i] = 1;
Rep(i, 2)
Rep(j, 2) {
Ret.Connect[i][j] |= A.Connect[i][j],
Ret.Connect[i+2][j+2] |= B.Connect[i+2][j+2];
}
Ret.Check();
Rep(k, 2)
For(i, 0, 1)
For(j, 2, 3)
Ret.Connect[i][j] |= A.Connect[i][k+2]&B.Connect[k][j];
Ret.Check();
Ret.Gone();
return Ret;
}
} ;
struct Node {
int Child[2];
State Map, Barrier;
//bool Con;
#define C(x, y) (S[x].Child[y])
#define M(x, L, R) (S[x].Map.Connect[L][R])
#define B(x, L, R) (S[x].Barrier.Connect[L][R])
#define Lc(x) (S[x].Child[0])
#define Rc(x) (S[x].Child[1])
//#define Con(x) (S[x].Con)
} S[N*2];
int Tot;
int n;
string Opt;

inline void Input() {
scanf("%d", &n);
}

inline void Build(int Left, int Right) {
int x = ++Tot, Mid = (Left+Right)>>1;
Rep(i, 4) B(x, i, i) = 1;
if(Left == Right) {
Rep(i, 4) M(x, i, i) = 1;
Rep(i, 2)
M(x, i, i+2) = M(x, i+2, i) = 1;
return;
}
Lc(x) = Tot+1, Build(Left, Mid);
Rc(x) = Tot+1, Build(Mid+1, Right);
}

inline void Updata(int x) {
S[x].Map = S[Lc(x)].Map+S[x].Barrier;
S[x].Map = S[x].Map+S[Rc(x)].Map;
}

inline void Change(int x, int Left, int Right, int G, int E) {
if(Left == Right) {
Rep(i, 4)
Rep(j, 4) M(x, i, j) = E;
Rep(i, 4) M(x, i, i) = 1;
Rep(i, 2)
M(x, i, i+2) = M(x, i+2, i) = 1;
} else {
int Mid = (Left+Right)>>1;
if(G <= Mid) Change(Lc(x), Left, Mid, G, E);
else Change(Rc(x), Mid+1, Right, G, E);
Updata(x);
}
}

inline void Change(int x, int Left, int Right, int L, int R, int G, int E) {
int Mid = (Left+Right)>>1;
if(R <= Mid) Change(Lc(x), Left, Mid, L, R, G, E);
else if(L > Mid) Change(Rc(x), Mid+1, Right, L, R, G, E);
else B(x, G, G+2) = B(x, G+2, G) = E;
Updata(x);
}

inline State Ask(int x, int Left, int Right, int L, int R) {
int Mid = (Left+Right)>>1;
State Ret, Temp;
if(Left >= L && Right <= R) Ret = S[x].Map;
else if(R <= Mid) Ret = Ask(Lc(x), Left, Mid, L, R);
else if(L > Mid) Ret = Ask(Rc(x), Mid+1, Right, L, R);
else {
Ret = Ask(Lc(x), Left, Mid, L, R);
Temp = Ask(Rc(x), Mid+1, Right, L, R);
Ret = Ret+S[x].Barrier;
Ret = Ret+Temp;
Ret.Gone();
}
return Ret;
}

inline void Solve() {
Build(1, n);

string Opt;
int Lx, Ly, Rx, Ry;
State Temp, Ret;
while(1) {
cin>>Opt;
if(Opt == "Exit") break;

scanf("%d%d%d%d", &Ly, &Lx, &Ry, &Rx);
if(Lx > Rx) swap(Lx, Rx), swap(Ly, Ry);
Ly--, Ry--;
if(Opt == "Open") {
if(Lx == Rx) Change(1, 1, n, Lx, 1);
else Change(1, 1, n, Lx, Rx, Ly, 1);
} else if(Opt == "Close") {
if(Lx == Rx) Change(1, 1, n, Lx, 0);
else Change(1, 1, n, Lx, Rx, Ly, 0);
} else {
clr(Ret.Connect, 0);
Rep(i, 4) Ret.Connect[i][i] = 1;

Temp = Ask(1, 1, n, 1, Lx);
Rep(i, 2)
Rep(j, 2)
Ret.Connect[i][j] |= Temp.Connect[i+2][j+2];
Temp = Ask(1, 1, n, Rx, n);
Rep(i, 2)
Rep(j, 2)
Ret.Connect[i+2][j+2] |= Temp.Connect[i][j];
Temp = Ask(1, 1, n, Lx, Rx);
Ret.Add(Temp);
Ret.Gone();

char Ans = Ret.Connect[Ly][Ry+2] ? 'Y' : 'N';
printf("%c\n", Ans);
}
}
}

int main() {
SetIO("1018");
Input();
Solve();
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: