zoukankan      html  css  js  c++  java
  • 2015编程之美复赛

    第一题,不道是什么鬼。。

    第二题猜数字。

    很多用主席树,我不会,啊啊啊~~~~记得这题有出过吧,想了一发线段树的,把所有的数排序,同时把询问K排序,

    做两发遍历,首先从小到大遍历所有的数,单点更新比K小的线段树的点,维护最大值,遇到>=K时则查询一发。

    再从大到小遍历,更新比k大的,维护最小值,遇<=K时就查询。比较即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    const int N= 200020;
    const int inf=1000000099;
    int seg[N*4];
    struct No{
    	int val,pos;
    }node[N];
    
    struct Qu{
    	int l,r,k,index;
    }query[N];
    int tree_index[N];
    int ans[N];
    bool cmp1(No a,No b){
    	if(a.val<b.val) return true;
    	return false;
    }
    bool cmp2(Qu a,Qu b){
    	if(a.k<b.k) return true;
    	return false;
    }
    int n,q;
    
    void build1(int rt,int l,int r){
    	seg[rt]=-inf;
    	if(l==r){
    		tree_index[l]=rt; return ;
    	}
    	int mid=(l+r)>>1;
    	build1(rt<<1,l,mid);
    	build1(rt<<1|1,mid+1,r);
    }
    void update1(int rt,int val){
    	seg[rt]=val;
    	rt/=2;
    	while(rt){
    		seg[rt]=max(seg[rt<<1],seg[rt<<1|1]);
    		rt/=2;
    	}
    }
    
    void build2(int rt,int l,int r){
    	seg[rt]=inf;
    	if(l==r){
    		tree_index[l]=rt; return ;
    	}
    	int mid=(l+r)>>1;
    	build2(rt<<1,l,mid);
    	build2(rt<<1|1,mid+1,r);
    }
    void update2(int rt,int val){
    	seg[rt]=val;
    	rt/=2;
    	while(rt){
    		seg[rt]=min(seg[rt<<1],seg[rt<<1|1]);
    		rt/=2;
    	}
    }
    int queryMax(int rt,int l,int r,int L,int R){
    	if(l<=L&&R<=r){
    		return seg[rt];
    	}
    	int mid=(L+R)>>1;
    	if(l>=mid+1){
    		return queryMax(rt<<1|1,l,r,mid+1,R);
    	}
    	else if(r<=mid) return queryMax(rt<<1,l,r,L,mid);
    	return max(queryMax(rt<<1,l,r,L,mid),queryMax(rt<<1|1,l,r,mid+1,R));
    }
    
    int queryMin(int rt,int l,int r,int L,int R){
    	if(l<=L&&R<=r){
    		return seg[rt];
    	}
    	int mid=(L+R)>>1;
    	if(l>=mid+1){
    		return queryMin(rt<<1|1,l,r,mid+1,R);
    	}
    	else if(r<=mid) return queryMin(rt<<1,l,r,L,mid);
    	return min(queryMin(rt<<1,l,r,L,mid),queryMin(rt<<1|1,l,r,mid+1,R));
    }
    
    
    
    int main(){
    	int T,icase=0;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d%d",&n,&q);
    		for(int i=1;i<=n;i++){
    			scanf("%d",&node[i].val);
    			node[i].pos=i;
    		}
    		for(int i=1;i<=q;i++){
    			scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k);
    			query[i].index=i;
    			ans[i]=inf;
    		}
    		sort(node+1,node+1+n,cmp1);
    		sort(query+1,query+1+q,cmp2);
    		build1(1,1,n);
    		int j=1;
    		for(int i=1;i<=q;i++){
    			for(;node[j].val<=query[i].k&&j<=n;j++){
    				update1(tree_index[node[j].pos],node[j].val);
    			}
    			int t=queryMax(1,query[i].l,query[i].r,1,n);
    			if(t==-inf) continue;
    			ans[query[i].index]=min(ans[query[i].index],query[i].k-t);
    		}
    //		for(int i=1;i<=q;i++)
    //		printf("%d
    ",ans[i]);
    		j=n;
    		build2(1,1,n);
    		for(int i=q;i>0;i--){
    			for(;node[j].val>=query[i].k&&j>0;j--){
    				update2(tree_index[node[j].pos],node[j].val);
    			}
    			int t=queryMin(1,query[i].l,query[i].r,1,n);
    			if(t==inf) continue;
    			ans[query[i].index]=min(ans[query[i].index],t-query[i].k);
    		}
    		printf("Case #%d:
    ",++icase);
    		for(int i=1;i<=q;i++)
    		printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    

      

    第三题,机器人。

    感谢斌神。知道,对于同一种颜色,归并后相对顺序是不对的。处理出对某个颜色相对于某颜色,所有块要移动到最后位置经过的步数,斌神叫逆序。然后,优化一下,对于某种颜色,它之前已加入K种颜色(状态压缩),它要移动到最后,经过的步数。枚举各种状态dp[k]为该状态变颜色相连要的步数,枚举状态内的颜色,求出在该状态下,该颜色移动到最末所需的最少步数,比较。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define LL long long
    using namespace std;
    
    const LL inf=1100000000000LL;
    const int MAXN=100050;
    int robot[MAXN];
    LL dp[1<<17];
    int b[20]; LL num[20][20]; LL f[20][1<<17];
    int bit[20],loc[1<<17];
    
    int main(){
    	int T,icase=0;
    	bit[0]=1; loc[bit[0]]=0;
    	for(int i=1;i<17;i++){
    		bit[i]=(bit[i-1]*2);
    		loc[bit[i]]=i;
    	}
    	scanf("%d",&T);
    	while(T--){
    		int n,k;
    		scanf("%d%d",&n,&k);
    		for(int i=0;i<n;i++){
    			scanf("%d",&robot[i]);
    			robot[i]--;
    		}
    		memset(b,0,sizeof(b));
    		memset(num,0,sizeof(num));
    		for(int i=n-1;i>=0;i--){
    			for(int j=0;j<k;j++){
    				if(robot[i]!=j){
    					num[robot[i]][j]+=b[j];
    				}
    			}
    			b[robot[i]]++;
    		}
    		int tot=(1<<k);
    		for(int j=0;j<k;j++){
    			f[j][0]=0;
    			for(int i=1;i<tot;i++){
    				int t=i&(-i);
    				f[j][i]=f[j][i^t]+num[j][loc[t]];
    			}
    		}
    		for(int i=0;i<tot;i++)
    		dp[i]=inf;
    		dp[0]=0;
    		for(int i=0;i<tot;i++){
    			if(dp[i]==inf) continue;
    			for(int j=0;j<k;j++){
    				if(bit[j]&i) continue;
    				dp[i|bit[j]]=min(dp[i|bit[j]],dp[i]+f[j][i]);
    			}
    		}
    		printf("Case #%d: %lld
    ",++icase,dp[tot-1]);
    	}
    	return 0;
    }
    

      

    第四题。可以知道,若城市被包塔包围,则它至多在一个三角形内。而激活塔的费用远小于城市的,所以优先激活塔。对塔求一个凸包,看哪些点在凸包内,然后计算塔的最小环能把那些城市全包含,floyd即可,黙认为逆时针即可,计算那些城市是否在边的左边,在则可以连边,不在就不能。然后就计算即可。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <cmath>
    
    using namespace std;
    const int MAXN=110;
    const int inf=10000000;
    struct Point{
    	int x,y;
    }cities[MAXN],tower[MAXN],anscity[MAXN];
    int n,m,top,g,p;
    int pexres[MAXN];
    
    bool cmp(Point a,Point b){
    	if(a.y==b.y) return a.x<b.x;
    	return a.y<b.y;
    }
    
    bool multi(Point sp,Point ep,Point op){
    	return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y);
    }
    
    int Multi(Point p1,Point p2,Point p0){
    	return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
    }
    
    int inside(int index){
    	int i; int now;
    	for(i=0;i<top;i++){
    		now=Multi(tower[pexres[i]],tower[pexres[(i+1)%top]],cities[index]);
    		if(now<=0) return 0;
    	}
    	return 1;
    }
    
    void Graham(){
    	int i,len;
    	top=1;
    	sort(tower,tower+n,cmp);
    	if(n==0) return ; pexres[0]=0;
    	if(n==1) return ; pexres[1]=1;
    	if(n==2) return ; pexres[2]=2;
    	for(i=2;i<n;i++){
    		while(top&&multi(tower[i],tower[pexres[top]],tower[pexres[top-1]])) top--;
    		pexres[++top]=i;
    	}
    	len=top;
    	pexres[++top]=n-2;
    	for(i=n-3;i>=0;i--){
    		while(top!=len&&multi(tower[i],tower[pexres[top]],tower[pexres[top-1]])) top--;
    		pexres[++top]=i;
    	}
    }
    int d[MAXN][MAXN];
    
    bool check(int i,int j,int cnt){
    	for(int k=0;k<cnt;k++){
    		int now=Multi(tower[i],tower[j],anscity[k]);
    		if(now<=0) return false;
    	}
    	return true;
    }
    
    int main(){
    	int T,icase=0;
    	scanf("%d",&T);
    	while(T--){
    		scanf("%d%d%d%d",&n,&m,&g,&p);
    		for(int i=0;i<n;i++){
    			scanf("%d%d",&tower[i].x,&tower[i].y);
    		}
    		for(int i=0;i<m;i++)
    		scanf("%d%d",&cities[i].x,&cities[i].y);
    		printf("Case #%d: ",++icase);
    		if(n<3){
    			printf("%d
    ",g*m);
    			continue;
    		}
    		Graham();
    	//	for(int i=0;i<=top;i++)
    	//	cout<<pexres[i]<<endl;
    		int cnt=0;
    		for(int i=0;i<m;i++){
    			if(inside(i)){
    				anscity[cnt++]=cities[i];
    			}
    		}
    		int len=inf;
    		if(cnt){
    			for(int i=0;i<n;i++){
    				for(int j=0;j<n;j++){
    					d[i][j]=inf;
    				}
    			}
    			for(int i=0;i<n;i++){
    				for(int j=0;j<n;j++){
    					if(i==j) continue;
    					if(check(i,j,cnt)){
    						d[i][j]=1;
    					}
    				}
    			}
    			for(int i=0;i<n;i++){
    				for(int j=0;j<n;j++){
    					for(int k=0;k<n;k++){
    						d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
    					}
    				}
    			}
    			for(int i=0;i<n;i++)
    			len=min(len,d[i][i]);
    		}
    		if(cnt==0) len=0;
    		printf("%d
    ",(m-cnt)*g+p*len);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    剖析虚幻渲染体系(12) 移动端专题Part 1(UE移动端渲染分析)
    剖析虚幻渲染体系(13) RHI补充篇:现代图形API之奥义与指南
    剖析虚幻渲染体系(12) 移动端专题Part 3(渲染优化)
    浏览器无环境调试
    RPC调用获取参数值
    vscode插件
    前端异常收集和处理
    互联网名词集锦
    今日思考20211104
    备忘项目进展萃取
  • 原文地址:https://www.cnblogs.com/jie-dcai/p/4523919.html
Copyright © 2011-2022 走看看