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]<h[i]且abs(i-j)<=w,那么d[j]=max(d[j],d[i]+1)

#include<bits/stdc++.h>
#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]&&abs(i-p)<=w)
		{
			d[i]=max(d[i],d[p]+1);
			ans=max(ans,d[i]);
		}
		h[p]=inf;p=0;
		for(int i=1;i<=n;i++)
		if(h[i]!=inf&&h[i]>h[p])p=i;
	}
	printf("%d\n",ans);
}

D. Bus Stop

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

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

#include<bits/stdc++.h>
#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<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=205;
vector<int>G[maxn];
int pre[maxn],lowlink[maxn],sccno[maxn],dfs_clock,scc_cnt;
stack<int>S;
void dfs(int u)
{
	pre[u]=lowlink[u]=++dfs_clock;
	S.push(u);
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i];
		if(!pre[v])
		{
			dfs(v);
			lowlink[u]=min(lowlink[u],lowlink[v]);
		}else if(!sccno[v])
		{
			lowlink[u]=min(lowlink[u],pre[v]);
		}
	}
	if(lowlink[u]==pre[u])
	{
		scc_cnt++;
		for(;;){
			int x=S.top();S.pop();
			sccno[x]=scc_cnt;
			if(x==u)break;
		}
	}
}
void find_scc(int n){
	dfs_clock=scc_cnt=0;
	memset(sccno,0,sizeof(sccno));
	memset(pre,0,sizeof(pre));
	for(int i=0;i<n;i++)
	if(!pre[i])dfs(i);
}

int main()
{
	int T,a,b,n,m;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		for(int i=0;i<n;i++)G[i].clear();
		for(int i=1;i<=m;i++)
		{
			scanf("%d%d",&a,&b);
			G[a].push_back(b);
		}
		find_scc(n);
		printf("%d\n",scc_cnt);
	}
}

K. The Stream of Corning 2

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

#include<bits/stdc++.h>
#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<v.t;
        return w.opt<v.opt;
    }
}s[maxn];//1 add, 2query 3 del
int cnt,ans[maxn],sum[maxn],b[maxn],tot;
void add(int Now,int L,int R,int pos,int val)
{
    sum[Now]+=val;if(L==R) return ;
    int Mid=(L+R)>>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<<s[i].opt<<" : "<<s[i].t<<" "<<s[i].val<<" "<<s[i].id<<endl;
           if(s[i].opt!=2){
              int pos=lower_bound(b+1,b+tot+1,s[i].val)-b;
              add(1,1,tot,pos,(s[i].opt==1)?1:-1);
           }
           else {
              if(sum[1]<s[i].val) ans[s[i].id]=-1;
              else ans[s[i].id]=query(1,1,tot,s[i].val);
              //cout<<s[i].val<<" ! "<<sum[1]<<"    "<<ans[s[i].id]<<endl;
           }
        }
        printf("Case %d:\n",++C);
        rep(i,1,N) {
           if(ans[i]==0) continue;
           if(ans[i]==-1) puts("-1");
           else printf("%d\n",b[ans[i]]);
        }
    }
    return 0;
}

L. Largest Allowed Area

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

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

#include<bits/stdc++.h>
#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;
}

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙橘子猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值