您的位置:首页 > 其它

[TOJ]3243 Blocked Road --线段树

2010-07-26 15:11 465 查看
这是以前写的了,树状数组做法在此

题意是有N个小岛,第i个岛与第 i%N+1 个岛之间有路

一共有两种操作:一个是把某条路的状态改变,如果能走改成不能走,vice versa;另一个是询问从 i 到 j 的路是否是通的。

要注意的是:i 可能比 j 大;第N个小岛与第一个小岛之间也有路,要从两个方向是不是通路。

我的程序效率不是很高,有0.25s的,貌似网上说树状数组也能做

Submit Time: 2010-07-26 10:12:15 Language: GNU C++ Result: Accepted
Pid: 3243 Time: 0.81 sec. Memory: 5888 K. Code Length: 1.7 K.

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define MAX 200010
int tot;
struct Node {int s,e;   int lt,rt,fa   ;bool flag; } tree[MAX];
void build(int fa,int a,int b){
int now = ++tot;
tree[now].s = a;
tree[now].e = b;
tree[now].fa = fa;
tree[now].flag=1;
if (b - a > 0){
tree[now].lt = tot + 1;
build(now,a,(a+b)/2);
tree[now].rt = tot + 1;
build(now,(a+b)/2+1,b);
} else {tree[now].lt = tree[now].rt = 0;}
}
void insert(int p,int a){
if(tree[p].s==tree[p].e&&a==tree[p].s) {tree[p].flag=!tree[p].flag;return ;}
int mid=(tree[p].s+tree[p].e)>>1;
if(a<=mid) insert(tree[p].lt,a);
else insert(tree[p].rt,a);
tree[p].flag=tree[tree[p].lt].flag && tree[tree[p].rt].flag;
}
bool ask(int p,int a,int b){
if(b<a) return true;
if (a <= tree[p].s && b >= tree[p].e) return tree[p].flag;
else {
int mid=(tree[p].s+tree[p].e)>>1;
if (b <= mid) return ask(tree[p].lt,a,b);
if (a >= mid+1) return ask(tree[p].rt,a,b);
return ask(tree[p].lt,a,mid) && ask(tree[p].rt,mid+1,b);
}
}
int main(){
int t,m,n,u,i,j,o;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
tot=0;
build(1,1,n);
while(m--){
scanf("%d",&o);
if(o){
scanf("%d%d",&i,&j);
if(i>j) swap(i,j);
if(ask(1,i,j-1)||(ask(1,1,i-1)&&ask(1,j,n))) printf("1/n");
else printf("0/n");
}
else {
scanf("%d",&i);
insert(1,i);
}
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: