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;
    }
    
  • 相关阅读:
    记一次安装python umysql模块的报错
    elasticsearch 6.2.4添加用户密码认证
    mysqldump 备份数据和恢复
    记一次线上Java程序导致服务器CPU占用率过高的问题排除过程
    配置rpm包安装的jdk环境变量
    centos6 & centos 7 防火墙设置
    MySQL启动出现The server quit without updating PID file错误解决办法
    ptmalloc,tcmalloc和jemalloc内存分配策略研究 ? I'm OWen..
    为什么要内存对齐 Data alignment: Straighten up and fly right
    linux驱动学习_1
  • 原文地址:https://www.cnblogs.com/ErkkiErkko/p/10492141.html
Copyright © 2011-2022 走看看