【GYM102091】2018-2019 ACM-ICPC, Asia Nakhon Pathom Regional Contest

A-Evolution Game

题目大意:有$n$个不同的野兽,定义第$i$ 个野兽有 $i$ 个眼睛和 $h[i]$ 个角,你可以任意从中选择一个野兽进行进化,每次进化角数量必须增加,而且进化后要满足眼镜的变化量 $\triangle i \leq w$,求最多的进化次数。

题解:以$h$的值从大到小排序,$f[i]$表示从第i个野兽开始进化的最多次数。对于$1 \leq i \leq j$若满足条件则$f[j]=max \{  f[i]+1 \}$。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cmath>
 5 #include<cstring>
 6 #include<algorithm>
 7 using namespace std;
 8 
 9 int n,w,ans;
10 int f[5005];
11 struct hh
12 {
13     int eye,horn;
14 }a[5005];
15 bool cmp(hh a,hh b)
16 {
17     return a.horn>b.horn;
18 }
19 int main()
20 {
21     int i,j;;
22     scanf("%d%d",&n,&w);
23     for(i=1;i<=n;i++)
24         scanf("%d",&a[i].horn);
25     for(i=1;i<=n;i++)
26         a[i].eye=i;
27     sort(a+1,a+1+n,cmp);
28     for(i=1;i<=n;i++)
29         for(j=i+1;j<=n;j++)//h[i]>h[j]
30             if(a[i].horn>a[j].horn&&abs(a[i].eye-a[j].eye)<=w)
31                 f[j]=max(f[j],f[i]+1);
32     for(i=1;i<=n;i++)
33         ans=max(f[i],ans);
34     printf("%d",ans);
35     return 0;
36 }
View Code

D-Bus Stop

题目大意:给出$n$个房子的坐标,要建立公交车站使得每个房子离最近的车站不过10公里,求最少的车站数。

题解:从左往右贪心即可。

#include <bits/stdc++.h>
using namespace std;
const int N=3e6;
int m,n;
int a[N];
int ans,lstop;
int main()
{
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d",&a[i]);
        }
        lstop=a[1]+10;
        ans=1;
        for(int i=2;i<=n;i++){
            if(abs(a[i]-lstop)<=10){
                ;
            }
            else{
                lstop=a[i]+10;
                ans++;
            }
        }
        if(n==0)ans=0;
        if(n==1)ans=1;
        printf("%d\n",ans);
    }
}
View Code

G-Communication

题目大意:求有向图强连通分量数。

题解:Floyed+并查集或者Tarjan。

#include <bits/stdc++.h>
using namespace std;
const int N=1e3;
int m,n,c,ans,a,b;
int f[N];
int edge[N][N];
int fnd(int x)
{
    if(f[x]==x)return x;
    return f[x]=fnd(f[x]);
}
int main()
{
    scanf("%d",&m);
    while(m--)
    {
        scanf("%d%d",&n,&c);
        memset(edge,0,sizeof(edge));
        for(int i=0;i<n;i++)
            f[i]=i;
        for(int i=1;i<=c;i++){
            scanf("%d%d",&a,&b);
            edge[a][b]=1;
        }
        for(int k=0;k<n;k++)
            for(int i=0;i<n;i++)
                for(int j=0;j<n;j++){
                    if(edge[i][k]&&edge[k][j])edge[i][j]=1;
                }
        ans=0;
        for(int i=0;i<n-1;i++)
            for(int j=i+1;j<n;j++){
                if(edge[i][j]+edge[j][i]==2){
                    f[j]=fnd(i);
                }
            }
        for(int i=0;i<n;i++){
            if(f[i]==i)ans++;
        }
        printf("%d\n",ans);
    }
}
View Code

H-As rich as Crassus

题目大意:$x^3 \equiv A_i  \ \ (mod \ \  N_i) (i=3)$,求$x$。

题解:中国剩余定理

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int n,t;
long long ans;
long long b[15],m[15];
long long exgcd(long long a,long long b,long long &x,long long &y){
    if(b==0){x=1,y=0;return a;}
    long long d=exgcd(b,a%b,x,y);
    long long z=x;x=y,y=z-a/b*y;
    return d;
}
void print(long long x){
    if(!x) return;
    if(x) print(x/10);
    putchar(x%10+'0');
}
int main()
{
    int i;
    long long x,y,M,aa,bb,cc,d,tmp;
    bool flag;n=3;
    scanf("%d",&t);
    while(t--)
    {
        ans=flag=0;
        for(i=1;i<=n;i++)
            scanf("%I64d",&m[i]);
        for(i=1;i<=n;i++)
            scanf("%I64d",&b[i]);
        M=m[1],ans=b[1];
        for(i=2;i<=n;i++)
        {
            aa=M,bb=m[i],cc=(b[i]-ans%bb+bb)%bb;
            x=0,y=0;
            d=exgcd(aa,bb,x,y);
            bb=bb/d;
            if(cc%d){flag=1;break;}
            x=((x*cc/d)%bb+bb)%bb;
            ans+=M*x;M*=bb;
            ans=(ans%M+M)%M;
        }
        if(flag)puts("-1");
        else {
            if(!ans)puts("0");
            else
            {
                tmp=pow(ans,1.0/3.0);
                if(tmp*tmp*tmp<ans) printf("%I64d\n",tmp+1);
                else printf("%I64d",tmp);
            }
        }            
    }
    return 0;
}
close
View Code

J-Floating-Point Hazard

题目大意:给出L,R,求$\sum_{i=L}^{R}(\sqrt[3]{i+10^{-15}}-\sqrt[3]{i})$。

题解:微分

#include <iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int main()
{
    #ifdef LOCAL
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
    #endif // LOCAL
    int a,b;
    while(~scanf("%d%d",&a,&b)){
        if(!a||!b) break;
        double ans=0;
        for(ll i=a;i<=b;i++){
            ans+=pow(i*i,-1/3.0);
        }
        ans*=1.0/3*(1e-15);
        printf("%.5E\n",ans);
    }
}
View Code

K-The Stream of Corning 2

题目大意:给出若干个数和存在的时间点,问某一时刻存在的数中的第k大。

题解:将一个操作的起始点和终止点拆开标记,按时间排序后,用树状数组+二分求动态第k大数。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
int t,n,totp,totq,lim;
struct hh
{
    int opt,t,v,k,id; 
}p[200005],q[200005];
int c[20000005];
int lowbit(int x)
{
    return x&(-x);
}
void add(int pos,int v)
{
    for(;pos<=lim;pos+=lowbit(pos))
        c[pos]+=v;
}
int query(int pos)
{
    int ret=0;
    for(;pos;pos-=lowbit(pos))
        ret+=c[pos];
    return ret;
}
bool cmp(hh a,hh b)
{
    return a.t<b.t;
}
bool cmp2(hh a,hh b)
{
    return a.id<b.id;
}
int solve(int k)
{
    int l,r,mid,ret,n;
    l=1;r=lim;
    ret=lim;
    if(query(lim)<k) return -1;
    while(l<=r)
    {
        mid=l+r>>1;
        if(query(mid)>=k)
        {
            r=mid-1;
            ret=min(ret,mid);
        }
        else l=mid+1;
    }
    return ret;
}
int main()
{
    int T,i,j,a,b,z,prep,opt;
    scanf("%d",&t);
    for(T=1;T<=t;T++)
    {
        scanf("%d",&n);
        totp=totq=0;
        memset(p,0,sizeof(p));
        memset(q,0,sizeof(q));
        memset(c,0,sizeof(c));
        for(i=1;i<=n;i++)
        {
            scanf("%d%d%d",&opt,&a,&b);
            lim=max(lim,b);
            if(opt==1)
            {
                scanf("%d",&z);
                p[++totp].opt=1;
                p[totp].v=b;
                p[totp].t=a;
                
                p[++totp].opt=-1;
                p[totp].v=b;
                p[totp].t=z;
            }
            else
            {
                q[++totq].t=a;
                q[totq].k=b;
                q[totq].id=i;
            }
        }
        sort(p+1,p+1+totp,cmp);
        sort(q+1,q+1+totq,cmp);
        prep=1;
        for(i=1;i<=totq;i++)
        {
            while(p[prep].t<q[i].t&&prep<=totp)
            {
                add(p[prep].v,p[prep].opt);
                prep++;
            }
            q[i].v=solve(q[i].k);
        }
        sort(q+1,q+1+totq,cmp2);
        printf("Case %d:\n",T);
        for(i=1;i<=totq;i++)
            printf("%d\n",q[i].v);
    }
    return 0;
}
View Code

L-Largest Allowed Area

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

题解:单调队列。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;

int t,n,m,ans;
int s[1005][1005],a[1005][1005];
char c;

int main()
{
    int i,j;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        memset(s,0,sizeof(s));
        memset(a,0,sizeof(a));
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
            {
                do{c=getchar();}while(c!='0'&&c!='1');
                s[i][j]=c-'0'+s[i-1][j]+s[i][j-1]-s[i-1][j-1];
            }
        for(i=1,ans=1;i<=n;i++)
            for(j=1;j<=m;j++)
            {
                a[i][j]=a[i-1][j-1]-(a[i-1][j-1]>=1);
                while(i+a[i][j]<=n&&j+a[i][j]<=m&&s[i+a[i][j]][j+a[i][j]]-s[i-1][j+a[i][j]]-s[i+a[i][j]][j-1]+s[i-1][j-1]<=1)
                    a[i][j]++;
                ans=max(ans,a[i][j]);
            }
        printf("%d\n",ans);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/yljiang/p/10545991.html