题解 P3588 【[POI2015]PUS】

whyl

2019-10-01 21:15:41

Solution

今天我才算是真正意义上理解了线段树优化建图 以前我只会一个点想一段区间连边 还不会许多点想许多区间连边 (其实本质意义上是一样的啊。。。) 唯一一个不同的就是要不要新开一个节点 连接两部分罢了 最后拓扑DP判断有无解 看是否有环是否满足范围即可 (其实最后要判a[i]是不是有小于0的 如果有小于0的 那就是无解 但是我没判也A掉了 懒得改了 ) 放代码(其实我的代码很亲民的。。。) ```cpp #include<bits/stdc++.h> using namespace std; #define mid ((l+r)>>1) #define lson k<<1,l,mid #define rson k<<1|1,mid+1,r inline int read(){ int x=0,f=1; char p=getchar(); while(!isdigit(p)){ if(p=='-') f=-1; p=getchar(); } while(isdigit(p)) x=(x<<3)+(x<<1)+p-48,p=getchar(); return x*f; } const int maxn=2e5+5; int n,s,m,a[maxn<<3],head[maxn<<3],ver[maxn<<3],in[maxn<<3],len; int nxt[maxn<<3],cnt,tot,bel[maxn<<3],pos[maxn<<3],xue[maxn<<3]; inline void add(int x,int y){ nxt[++cnt]=head[x]; head[x]=cnt; ver[cnt]=y; } inline void build(int k,int l,int r){ if(l==r){ bel[k]=l; pos[l]=k; return; } tot=max(tot,k<<1|1); add(k,k<<1); in[k<<1]++; add(k,k<<1|1); in[k<<1|1]++; build(lson); build(rson); } inline void connect(int k,int l,int r,int L,int R,int pos){ if(L>R) return ; if(L<=l&&r<=R){ add(pos,k); in[k]++; return ; } if(L<=mid) connect(lson,L,R,pos); if(R>mid) connect(rson,L,R,pos); return; } inline void topsort(){ queue<int> q; q.push(1); a[1]=1e9; memset(xue,127,sizeof(xue)); while(!q.empty()){ int x=q.front();q.pop(); for(int i=head[x];i;i=nxt[i]){ int y=ver[i]; if(bel[y]) xue[y]=min(xue[y],a[x]-1); else xue[y]=min(xue[y],a[x]); if(xue[y]<a[y]){ cout<<"NIE\n"; exit(0); } in[y]--; if(in[y]==0){ if(bel[y]) len++; q.push(y); if(a[y]==0) a[y]=xue[y]; } } } } int main(){ n=read();s=read();m=read(); build(1,1,n); for(int i=1;i<=s;i++){ int x=read(),y=read(); a[pos[x]]=y; } // for(int i=1;i<=n;i++) cout<<pos[i]<<" "; // cout<<endl<<endl; // for(int i=1;i<=n;i++) cout<<a[pos[i]]<<" "; // cout<<endl<<endl; for(int i=1;i<=m;i++){ int l=read(),r=read(),k=read(); int last=l; int node_cnt=++tot; while(k--){ int x=read(); // cout<<pos[x]<<" "<<node_cnt<<endl; add(pos[x],node_cnt); in[node_cnt]++; // cout<<last<<" "<<x-1<<" "<<node_cnt<<endl; connect(1,1,n,last,x-1,node_cnt); last=x+1; } // cout<<last<<" "<<r<<" "<<node_cnt<<endl; connect(1,1,n,last,r,node_cnt); // cout<<endl; } topsort(); if(len!=n){ cout<<"NIE\n"; return 0; } cout<<"TAK\n"; for(int i=1;i<=n;i++) cout<<a[pos[i]]<<" "; cout<<endl; return 0; } ```