zoukankan      html  css  js  c++  java
  • #差分约束系统,最长路,线段树优化建边#洛谷 3588 [POI2015] PUS

    题目

    给定一个长度为(n)的正整数序列 (a) ,每个数都在 (1)(10^9) 范围内,

    告诉你其中 (s) 个数,并给出 (m) 条信息,每条信息包含三个数 (l,r,k) 以及接下来 (k) 个正整数,

    表示 (a_l..a_{l+1}...a_{r-1}..a_r) 里这 (k) 个数中的任意一个都比任意一个剩下的 (r-l+1-k) 个数大 (严格大于,即没有等号)。


    分析

    考虑约束条件形如(a[x]+1<a[y]),建边跑最长路即可,
    现在问题是建边,考虑线段树优化建边,
    由于它有已知值,所以要在已知值的基础上跑最长路,
    如果约束条件有环那无解,最小答案超过已知值无解


    代码

    #include <cstdio>
    #include <cctype> 
    #define rr register
    using namespace std;
    const int N=1000011; struct node{int y,w,next;}e[N<<2];
    int ls[N],rs[N],deg[N],dis[N],a[N],n,cnt,m,T,et,as[N],root,p[N],q[N],head=1,tail;
    inline signed iut(){
    	rr int ans=0; rr char c=getchar();
    	while (!isdigit(c)) c=getchar();
    	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
    	return ans;
    }
    inline void print(int ans){
    	if (ans>9) print(ans/10);
    	putchar(ans%10+48);
    }
    inline void add(int x,int y,int w){
    	e[++et]=(node){y,w,as[x]},as[x]=et;
    }
    inline void build(int &k,int l,int r){
    	if (l==r) {k=l; return;}
    	if (!k) k=++cnt;
    	rr int mid=(l+r)>>1;
    	build(ls[k],l,mid);
    	build(rs[k],mid+1,r);
        add(ls[k],k,0),add(rs[k],k,0);
    }
    inline void update(int k,int l,int r,int x,int y,int z){
    	if (l==x&&r==y) {add(k,z,0); return;}
    	rr int mid=(l+r)>>1;
    	if (y<=mid) update(ls[k],l,mid,x,y,z);
    	else if (x>mid) update(rs[k],mid+1,r,x,y,z);
    	    else update(ls[k],l,mid,x,mid,z),update(rs[k],mid+1,r,mid+1,y,z);
    }
    signed main(){
    	cnt=n=iut(),T=iut(),m=iut();
    	for (rr int x;T;--T)
    	     x=iut(),dis[x]=a[x]=iut();
    	build(root,1,n);
    	for (rr int i=1;i<=m;++i){
    		rr int l=iut(),r=iut(); p[0]=iut();
    		for (rr int j=1;j<=p[0];++j) add(cnt+i,p[j]=iut(),1);
    		for (rr int j=1;j<p[0];++j) if (p[j]+1<p[j+1])
    		    update(root,1,n,p[j]+1,p[j+1]-1,cnt+i);
    		if (l<p[1]) update(root,1,n,l,p[1]-1,cnt+i);
    		if (p[p[0]]<r) update(root,1,n,p[p[0]]+1,r,cnt+i);
    	}
    	cnt+=m;
    	for (rr int i=1;i<=cnt;++i)
    	if (!deg[i]){
    		q[++tail]=i;
    		if (!dis[i]) dis[i]=1;
    	}
    	while (head<=tail){
    		rr int x=q[head++];
    		for (rr int i=as[x];i;i=e[i].next)
    		if (dis[e[i].y]<dis[x]+e[i].w){
    			dis[e[i].y]=dis[x]+e[i].w;
    			if (dis[e[i].y]>a[e[i].y]&&a[e[i].y])
    			    return !printf("NIE");
    			if (--deg[e[i].y]==0) q[++tail]=e[i].y;
    		}
    	}
    	for (rr int i=1;i<=cnt;++i)
    	if (deg[i]>0||dis[i]>1e9)
    	    return !printf("NIE");
    	printf("TAK");
    	for (rr int i=1;i<=n;++i) putchar(i==1?10:32),print(dis[i]); 
    	return 0;
    }
    
  • 相关阅读:
    第四次作业
    第三次作业
    Java.14
    Java.13
    JAVA.12
    JAVA.11
    JAVA.10
    JAVA.9
    JAVA.8
    JAVA.7
  • 原文地址:https://www.cnblogs.com/Spare-No-Effort/p/14980911.html
Copyright © 2011-2022 走看看