zoukankan      html  css  js  c++  java
  • USACO2018DEC PLATINUM

    就按(博主认为的)难度顺序排吧。

    Sort It Out

    分析

    容易发现选出的集合一定是所有逆序对的一个最小覆盖集,那么剩下的就一定是一个LIS。仔细想想还可以发现字典序第(k)小的最小覆盖集的补集一定是字典序第(k)大的LIS,所以找到这个序列字典序第(k)大的LIS就好了。

    代码

    #include <bits/stdc++.h>
    
    #define rin(i,a,b) for(register int i=(a);i<=(b);++i)
    #define irin(i,a,b) for(register int i=(a);i>=(b);--i)
    #define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
    typedef long long LL;
    
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline LL read(){
    	LL x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=100005;
    const LL inf=1e18+1;
    
    int n,a[MAXN],bit[MAXN],f[MAXN];
    LL k,retcnt,cnt[MAXN],g[MAXN];
    bool vis[MAXN];
    
    struct number{
    	int pos,val,f;LL g;
    	inline friend bool operator < (number x,number y){
    		return x.f==y.f?x.val>y.val:x.f>y.f;
    	}
    }b[MAXN];
    
    #define lowbit(x) ((x)&(-(x)))
    
    inline void upd(int x,int kk,LL ll){
    	for(register int i=x;i<=n;i+=lowbit(i)){
    		if(kk<bit[i]) continue;
    		else if(kk==bit[i]){
    			cnt[i]=std::min(cnt[i]+ll,inf);
    		}
    		else{
    			bit[i]=kk;
    			cnt[i]=ll;
    		}
    	}
    }
    
    inline int ask(int x){
    	int ret=0;retcnt=1;
    	for(register int i=x;i;i-=lowbit(i)){
    		if(bit[i]<ret) continue;
    		else if(bit[i]==ret){
    			retcnt=std::min(retcnt+cnt[i],inf);
    		}
    		else{
    			ret=bit[i];
    			retcnt=cnt[i];
    		}
    	}
    	return ret;
    }
    
    #undef lowbit(x)
    
    int main(){
    	n=read(),k=read();int ans=0;
    	rin(i,1,n) a[i]=read();
    	irin(i,n,1){
    		f[i]=ask(n-a[i]+1)+1;
    		g[i]=retcnt;
    		upd(n-a[i]+1,f[i],g[i]);
    		b[i]=(number){i,a[i],f[i],g[i]};
    		ans=std::max(ans,f[i]);
    	}
    	ans=n-ans;
    	std::sort(b+1,b+n+1);
    	int now=b[1].f,pos=0,las=0;LL temp=0;
    	rin(i,1,n){
    		if(b[i].f!=now||b[i].pos<pos||b[i].val<las) continue;
    		if(temp+b[i].g>=k){
    			k-=temp;
    			temp=0;
    			--now;
    			pos=b[i].pos;
    			las=b[i].val;
    			vis[b[i].val]=true;
    		}
    		else{
    			temp+=b[i].g;
    		}
    	}
    	printf("%d
    ",ans);
    	rin(i,1,n) if(!vis[i]) printf("%d
    ",i);
    	return 0;
    }
    

    The Cow Gathering

    分析

    有一个简单的结论,就是如果(a)必须比(b)先离开聚会,那么以(b)为根(a)的子树内的点的答案就一定是(0)

    但是明显这样还会有些问题。显然目前所有答案还有可能为(1)的点是连通的,因此一些树边的方向可以被确定。如果我们在已经确定了的关系中找到了环,那么说明整张图的所有点的答案就都是(0)

    尽管想到了正解但还是各种疑惑,可能之后会在这里补充一点东西。

    代码

    #include <bits/stdc++.h>
    
    #define rin(i,a,b) for(register int i=(a);i<=(b);++i)
    #define irin(i,a,b) for(register int i=(a);i>=(b);--i)
    #define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
    typedef long long LL;
    
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline LL read(){
    	LL x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=100005;
    
    int n,m,ecnt,head[MAXN];
    int top,sta[MAXN],pos[MAXN],tag[MAXN];
    int tot,uu[MAXN<<1],vv[MAXN<<1],deg[MAXN<<1];
    bool ok[MAXN];
    std::vector<int> vec[MAXN];
    
    struct Edge{
    	int to,nxt;
    }e[MAXN<<1];
    
    inline void add_edge(int bg,int ed){
    	++ecnt;
    	e[ecnt].to=ed;
    	e[ecnt].nxt=head[bg];
    	head[bg]=ecnt;
    }
    
    void dfs1(int x,int pre){
    	sta[++top]=x;
    	pos[x]=top;
    	rin(i,0,(int)vec[x].size()-1){
    		int ver=vec[x][i];
    		if(!pos[ver]) ++tag[ver];
    		else{
    			++tag[1];
    			--tag[sta[pos[ver]+1]];
    		}
    	}
    	trav(i,x){
    		int ver=e[i].to;
    		if(ver==pre) continue;
    		dfs1(ver,x);
    	}
    	--top;
    	pos[x]=0;
    }
    
    void dfs2(int x,int pre,int now){
    	now+=tag[x];
    	if(!now) ok[x]=true;
    	trav(i,x){
    		int ver=e[i].to;
    		if(ver==pre) continue;
    		dfs2(ver,x,now);
    	}
    }
    
    void dfs3(int x,int pre){
    	if(pre) ++tot,uu[tot]=pre,vv[tot]=x;
    	trav(i,x){
    		int ver=e[i].to;
    		if(ver==pre) continue;
    		dfs3(ver,x);
    	}
    }
    
    std::queue<int> q;
    
    void topo(){
    	while(!q.empty()) q.pop();
    	rin(i,1,n) if(!deg[i]) q.push(i);
    	int cnt=0;
    	while(!q.empty()){
    		int x=q.front();q.pop();
    		++cnt;
    		trav(i,x){
    			int ver=e[i].to;
    			--deg[ver];
    			if(!deg[ver]) q.push(ver);
    		}
    	}
    	if(cnt<n){
    		rin(i,1,n) printf("0
    ");
    		exit(0);
    	}
    }
    
    int main(){
    	n=read(),m=read();
    	rin(i,2,n){
    		int u=read(),v=read();
    		add_edge(u,v);
    		add_edge(v,u);
    	}
    	rin(i,1,m){
    		int u=read(),v=read();
    		vec[v].push_back(u);
    		++tot,uu[tot]=v,vv[tot]=u;
    	}
    	dfs1(1,0);
    	dfs2(1,0,0);
    	int root=0;
    	rin(i,1,n){
    		if(ok[i]){
    			root=i;
    			break;
    		}
    	}
    	if(!root){
    		rin(i,1,n) printf("0
    ");
    		return 0;
    	}
    	dfs3(root,0);
    	ecnt=0,memset(head,0,sizeof head);
    	rin(i,1,tot){
    		add_edge(uu[i],vv[i]);
    		++deg[vv[i]];
    	}
    	topo();
    	rin(i,1,n) printf("%d
    ",ok[i]?1:0);
    	return 0;
    }
    

    Balance Beam

    分析

    把期望和凸包结合在了一块,这道题有点神啊。。

    贴一个认为讲的不错的博客,本人就不在这里献丑了。

    戳我感受大神的洗礼

    代码

    #include <bits/stdc++.h>
    
    #define rin(i,a,b) for(register int i=(a);i<=(b);++i)
    #define irin(i,a,b) for(register int i=(a);i>=(b);--i)
    #define trav(i,a) for(register int i=head[a];i;i=e[i].nxt)
    typedef long long LL;
    
    using std::cin;
    using std::cout;
    using std::endl;
    
    inline int read(){
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    	while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
    	return x*f;
    }
    
    const int MAXN=100005;
    
    int n,f[MAXN],sta[MAXN],top;
    LL ans[MAXN];
    
    bool isleft(int x1,int y1,int x2,int y2,int x3,int y3){
    	int X1=x2-x1,Y1=y2-y1,X2=x3-x2,Y2=y3-y2;
    	return 1ll*X1*Y2-1ll*X2*Y1>=0;
    }
    
    int main(){
    	n=read();
    	rin(i,1,n) f[i]=read();
    	top=0;sta[++top]=0;
    	rin(i,1,n+1){
    		while(top>1&&isleft(sta[top-1],f[sta[top-1]],sta[top],f[sta[top]],i,f[i])) --top;
    		sta[++top]=i;
    	}
    	rin(i,2,top){
    		rin(j,sta[i-1]+1,sta[i])
    			ans[j]=(1ll*f[sta[i]]*(j-sta[i-1])+1ll*f[sta[i-1]]*(sta[i]-j))*100000/(sta[i]-sta[i-1]);
    	}
    	rin(i,1,n) printf("%lld
    ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    JS站点
    1011 World Cup Betting (20分)
    1007 Maximum Subsequence Sum (25分)(动态规划DP)
    1006 Sign In and Sign Out (25分)
    1005 Spell It Right (20分)
    1004 Counting Leaves (30分)(DFS)
    1003 Emergency (25分)(Dijkstra算法)
    1002 A+B for Polynomials (25分)
    1001 A+B Format (20分)
    canvas
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10492141.html
Copyright © 2011-2022 走看看