题意:一棵树结构上有水,往一个节点加水,那么所有的子节点都会有水,或者排干一个节点的水,那么它的上面的节点都会没水。
用dfs序,数组记录区间内全部有水为1,区间内有没水的点就为0。
倒水:区间更新,排水:单点更新,并更新途中经过的所有点,查询:区间查询。
倒水:区间内所有的点变为有水,就是1,用lazy数组,要下传。
排水:所有节点的dfs序之间的相交只能是包含,并且只被祖先包含。那么在线段树中就将经过的点全部排去。这样祖先节点查询时就为0了,并且无关节点还是有水。不过这样有个BUG,假如开始全有水,如果一个节点排空了立即加水,那么祖先又有水了,实际上是没水,这时将祖先排水就行。
6 2 1 3 1 4 1 4 5 2 6 4 1 1 2 4 1 4 3 1就这。
#include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <vector> #include <iomanip> #include <cstring> #include <map> #include <queue> #include <set> #include <cassert> #include <stack> #include <bitset> #include <unordered_set> #define mkp make_pair using namespace std; const double EPS=1e-8; typedef long long lon; const lon SZ=500010,SSZ=10*SZ,APB=20,INF=0x7FFFFFFF,mod=1000000007; lon n,bg[SZ],fn[SZ],cnt,arr[SSZ],lazy[SSZ]; lon pre[SZ]; vector<int> mp[SZ]; void release() { } void dfs(int x,int p) { bg[x]=++cnt; pre[x]=p; for(int i=0;i<mp[x].size();++i) { int to=mp[x][i]; if(to!=p) { dfs(to,x); } } fn[x]=cnt; } void pushdown(int rt) { if(lazy[rt]) { lazy[rt*2]=lazy[rt*2+1]=1; arr[rt*2]=arr[rt*2+1]=1; lazy[rt]=0; } } void pushup(int rt) { arr[rt]=arr[rt*2]*arr[rt*2+1]; } void update(int ll,int rr,int rt,int ql,int qr) { int mid=(ll+rr)/2; pushdown(rt); if(ql<=ll&&rr<=qr) { arr[rt]=1; lazy[rt]=1; return; } if(ll>rr)return; if(ql<=mid)update(ll,mid,rt*2,ql,qr); if(qr>mid)update(mid+1,rr,rt*2+1,ql,qr); pushup(rt); } void update(int ll,int rr,int rt,int pos) { int mid=(ll+rr)/2; pushdown(rt); if(ll==rr) { arr[rt]=0; return; } if(pos<=mid)update(ll,mid,rt*2,pos); else update(mid+1,rr,rt*2+1,pos); pushup(rt); } int qry(int ll,int rr,int rt,int ql,int qr) { //cout<<" "<<ll<<" "<<rr<<endl; int mid=(ll+rr)/2; pushdown(rt); if(ql<=ll&&rr<=qr) { return arr[rt]; } if(ll>rr)return 1; int res1=1,res2=1; if(ql<=mid)res1=qry(ll,mid,rt*2,ql,qr); if(qr>mid)res2=qry(mid+1,rr,rt*2+1,ql,qr); return res1*res2; } void init() { cin>>n; for(int i=1;i<=n-1;++i) { int a,b; cin>>a>>b; mp[a].push_back(b); mp[b].push_back(a); } dfs(1,-1); } void work() { int qnum; cin>>qnum; for(int i=1;i<=qnum;++i) { int type,x; cin>>type>>x; if(type==1) { if(x!=1&&!qry(1,cnt,1,bg[x],fn[x]))update(1,cnt,1,bg[pre[x]]); update(1,cnt,1,bg[x],fn[x]); } else if(type==2) { update(1,cnt,1,bg[x]); } else { //cout<<"3: "<<bg[x]<<" "<<fn[x]<<endl; cout<<qry(1,cnt,1,bg[x],fn[x])<<endl; } } } int main() { //std::ios::sync_with_stdio(0); //freopen("d:\\2.txt","r",stdin); //freopen("d:\\3.txt","w",stdout); lon casenum; //cin>>casenum; //cout<<casenum<<endl; //for(lon time=1;time<=casenum;++time) //for(lon time=1;scanf("%d%d",&n,&m)!=EOF;++time) { init(); work(); release(); } return 0; }