2018-2019 ACM-ICPC, Asia Nakhon Pathom Regional Contest 寒假自训第二场

跟着付队一起打的第二场gym,差点就被付队爆0了,还好趁他不注意切了两个水题(付队tql)

C.Evolution Game

题意:有n个不同版本的野兽,定义属性:第 i 个野兽有 i 个眼睛和 h[i] 个角,你可以任意从中选择一个野兽进行进化,每次进化角数量必须增加,而且进化后假设有a 个眼睛 b个角,假设h[i]=b,那么abs(a-i)<=w,否则不能进化,求最多的进化次数。

思路:从大到小枚举h[i]的值,设d[i]为从第 i 个野兽开始进化所能得到的答案,如果对于 j,h[j]

#include
#define ll long long
using namespace std;
const int maxn=5005,inf=1e9;
int d[maxn],h[maxn];
int main()
{
	int n,w,p=0,ans=0;
	scanf("%d%d",&n,&w);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&h[i]);
		if(h[i]>h[p])p=i;
	}
	int m=n;
	while(m--)
	{
		for(int i=1;i<=n;i++)
		if(h[i]h[p])p=i;
	}
	printf("%d\n",ans);
}

D. Bus Stop

题意:有n个房子的坐标,你要建立公交车站,使得每个房子离最近的车站不过10公里,求最少的车站。

思路:直接贪心,从左往右遍历房子,如果一个房子没被覆盖,就在他右边10公里建车站即可。

#include
#define ll long long
using namespace std;
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		int n,x,p=-100,ans=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&x);
			if(x>p+10)
			ans++,p=x+10;
		}
		printf("%d\n",ans);
	}
}

G. Communication

题意:给一些有向边,如果两个点可以互达,那么这两个点属于同一组,求你给有向图分组。

思路:就是强连通裸题。

#include
#define ll long long
using namespace std;
const int maxn=205;
vectorG[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
stackS;
void dfs(int u)
{
	pre[u]=lowlink[u]=++dfs_clock;
	S.push(u);
	for(int i=0;i

K. The Stream of Corning 2

付队写的,我还有事先溜了,贴付队线段树代码:

#include
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=400010;
struct in{
    int opt,t,val,id;
    in(){}
    in(int oo,int tt,int vv):opt(oo),t(tt),val(vv){}
    friend bool operator <(in w,in v){
        if(w.t^v.t) return w.t>1;
    if(pos<=Mid) add(Now<<1,L,Mid,pos,val);
    else add(Now<<1|1,Mid+1,R,pos,val);
}
int query(int Now,int L,int R,int K)
{
    if(L==R) return L; int Mid=(L+R)>>1;
    if(sum[Now<<1]>=K) return query(Now<<1,L,Mid,K);
    return query(Now<<1|1,Mid+1,R,K-sum[Now<<1]);
}
int main()
{
    int C=0,T,N,M,Mx,op,x,y,z;
    scanf("%d",&T);
    while(T--){
        scanf("%d",&N); tot=0; cnt=0;
        rep(i,1,N){
            scanf("%d%d%d",&op,&x,&y);
            if(op==1) {
                scanf("%d",&z);
                s[++cnt]=in(1,x,y);
                s[++cnt]=in(3,z,y);
                b[++tot]=y;
            }
            else s[++cnt]=in(2,x,y);
            s[cnt].id=i;
            ans[i]=0;
        }
        sort(b+1,b+tot+1);
        tot=unique(b+1,b+tot+1)-(b+1);
        sort(s+1,s+cnt+1);
        rep(i,1,tot<<1) sum[i]=0;
        rep(i,1,cnt){
           //cout<

L. Largest Allowed Area

题意:求一个最大的子矩阵,子矩阵的和要么为0要么为1。

贴付队单调队列代码(明天回来补完):

#include
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1010;
char c[maxn][maxn];
int ans[maxn][maxn],sum[maxn][maxn];
int main()
{
    int T,N,M,Mx;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&N,&M); Mx=0;
        rep(i,1,N)
         rep(j,1,M){
           c[i][j]=getchar();
           while(c[i][j]!='0'&&c[i][j]!='1') c[i][j]=getchar();
           //scanf("%d",&c[i][j]),
           sum[i][j]=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+(c[i][j]=='1');
         }
        rep(i,1,N)
         rep(j,1,M){
            ans[i][j]=ans[i-1][j-1]-1;
            if(ans[i][j]<1) ans[i][j]=1;
            while(i+ans[i][j]<=N&&j+ans[i][j]<=M&&(sum[i+ans[i][j]][j+ans[i][j]]-sum[i-1][j+ans[i][j]]-sum[i+ans[i][j]][j-1]+sum[i-1][j-1]<=1)) ans[i][j]++;
            Mx=max(Mx,ans[i][j]);
        }
        printf("%d\n",Mx);
    }
    return 0;
}

 

你可能感兴趣的:(比赛----gym)