zoukankan      html  css  js  c++  java
  • Gym101986: Asia Tsukuba Regional Contest(寒假自训第12场)

    A .Secret of Chocolate Poles

    题意:有黑白两种木块,黑色有1,K两种长度; 白色只有1一种长度,问满足黑白黑...白黑形式,长度为L的组合种类。

    思路:直接DP即可。

    #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=200010;
    ll dp[110][2],ans;
    int main()
    {
        int L,K;
        scanf("%d%d",&L,&K);
        dp[0][0]=1;
        rep(i,1,L){
            dp[i][0]=dp[i-1][1];
            dp[i][1]=dp[i-1][0];
            if(i-K>=0) dp[i][1]+=dp[i-K][0];
        }
        rep(i,1,L) ans+=dp[i][1];
        printf("%lld
    ",ans);
        return 0;
    }

    B .Parallel Lines

    题意:给定二维平面上N个点,N是偶数,限制让你两两连线,使得平行线对数最多。N<=16;

    思路:N为16时,复杂度=15*13*11*9*7*5*3*1~=2e6;所以可以枚举所有情况,即搜索可以做。 注意是两两配对,没有不选的情况,不然复杂度很高。

    统计时用了map带了个log。 这个log还可以优化掉,比如,变为每次加入一个斜率x时,res+=num[x];  num[x]++; 就不用map记录每个斜率的个数,最后才去统计答案了。  

    #include<bits/stdc++.h>
    #define ll long long
    #define pii pair<int,int>
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=20;
    int X[maxn],Y[maxn],ans,N,vis[maxn];
    map<pii,int>mp; map<pii,int>::iterator it;
    pii a[maxn][maxn];
    void dfs(int pos)
    {
        if(pos==N+1){
            int res=0;
            for(it=mp.begin();it!=mp.end();it++){
                res+=(it->second)*((it->second)-1)/2;
            }
            ans=max(ans,res);
            return ;
        }
        if(!vis[pos])
         for(int i=pos+1;i<=N;i++){
            if(!vis[i]){
                vis[i]=1;
                mp[a[pos][i]]++;
                dfs(pos+1);
                mp[a[pos][i]]--;
                vis[i]=0;
            }
        }
        else dfs(pos+1);
    }
    int main()
    {
        scanf("%d",&N);
        rep(i,1,N) scanf("%d%d",&X[i],&Y[i]);
        rep(i,1,N) rep(j,i+1,N){
            int dx=X[j]-X[i],dy=Y[j]-Y[i];
            if(dx<0) dx=-dx,dy=-dy;
            if(dx==0) dy=abs(dy);
            int g=__gcd(dx,dy);
            dx/=g; dy/=g;
            a[i][j]=pii(dx,dy);
        }
        dfs(1);
        printf("%d
    ",ans);
        return 0;
    }

    C .Medical Checkup

    题意:有有无限个医院,N个学生,第i个学生在每个医院检查的时间都一样,是hi。 他们排成一队去检查。 满足,一个医院不能同时检查多个人,一个人前面的那个人检查完后才能去检查, 给定时间T,问每个人在哪个医院里检查(或者在等候)。

    思路:对思维题不感冒啊,想的过于复杂了。  这个题,对于所有的人都满足的东西是开始入队的时间是一定的,即h1+h2+...hi-1。

    然后,从他开始检查开始,就把入队的看成一个整体,那么,这个整体的队尾前进的距离,取决于整个队伍前进的最小距离。

    所以不难得出他们的答案=(T-h1-h2-...)/hi+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=200010;
    ll h[maxn];
    int main()
    {
        int N; ll sum=0,T,Mx=0;
        scanf("%d%lld",&N,&T);
        rep(i,1,N){
            scanf("%lld",&h[i]);
            Mx=max(Mx,h[i]);
            sum+=h[i];
            if(T>=sum) printf("%lld
    ",(T-sum )/Mx+2);
            else printf("1
    ");
        }
        return 0;
    }

    E .Black or White

    题意:给定一排,N个砖,只有黑白两色,给出它们初始的颜色S,限制你有长度为1到K的刷子,问至少刷多少次,可以把它们刷成给定状态T。

    思路:假设一排长度为M的没有颜色砖,染色成BWBWBW..的形式,至少需要(M+1)/2+1刷子。 所以其实初始状态没有多大用处(除非相同),我们只考虑目标状态。

    我们把T种相邻颜色相同的看成一个整体,那么:

        dp[i]=dp[i-1];  当s[i]==t[i];

        dp[i]=dp[j]+(sum[i]-sum[j+1]+1)/2+1;  当s[i]!=t[i];

    第二个方程直接单调队列可以搞。  如果我们考虑了初始状态,那么只会越想越复杂。

    #include<bits/stdc++.h>
    #define rep(i,w,v) for(int i=w;i<=v;i++)
    using namespace std;
    const int maxn=500001;
    int dp[maxn],sum[maxn],q[maxn],head,tail,N,K;
    char a[maxn],b[maxn];
    int main()
    {
        scanf("%d%d",&N,&K);
        scanf("%s%s",a+1,b+1);
        rep(i,1,N) sum[i]=sum[i-1]+(b[i]!=b[i-1]);
        head=tail=1; q[1]=0;
        rep(i,1,N){
            if(a[i]==b[i]) dp[i]=dp[i-1];
            else
             dp[i]=dp[q[head]]+(sum[i]-sum[q[head]+1]+1)/2+1;
            while(tail>=head&&dp[i]*2-sum[i+1]<=dp[q[tail]]*2-sum[q[tail]+1]) tail--;
            while(tail>=head&&i-q[head]>=K) head++;
            q[++tail]=i;
        }
        printf("%d
    ",dp[N]);
        return 0;
    }

    I  .Starting a Scenic Railroad Service

    题意:给定N个人的陆游线路,问自己选票的情况下,和售票方选票的情况下,旅游车需要多少个位置。

    思路:反正题意差不多是这样,第一个问是问max(一个人的路线+和他规范相交的路线个数)。 第二个问是max(单点最大路线覆盖);

    第二个问,由于数据小,可以用差分或者线段树; 如果数据大,可以直接排序做。 是个常规题了。

    第一个问,和一个线段相交的线段个数,=N-在他前面的-在他后面的。 不难想到也可以差分去做。 数据大后还是可以排序来做。

    覆盖问题,个人更喜欢写排序,因为不用考虑下标大小,或者离散化导致的边界问题。

    #include<bits/stdc++.h>
    #define ll long long
    #define pii pair<int,int>
    #define f first
    #define s second
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=1000000;
    pii a[maxn],b[maxn];
    int A[maxn],B[maxn],ans1,ans2,tot;
    int main()
    {
        int N,pre=0; scanf("%d",&N);
        rep(i,1,N) {
           scanf("%d%d",&a[i].f,&a[i].s);
           b[++tot]=pii(a[i].f,1);
           b[++tot]=pii(a[i].s,-1);
        }
        rep(i,1,N){
             A[a[i].f]++;
             B[a[i].s]++;
        }
        rep(i,1,100000) A[i]+=A[i-1],B[i]+=B[i-1];
        rep(i,1,N){
            int f=B[a[i].f]+N-A[a[i].s-1];
            ans1=max(ans1,N-f);
        }
        sort(b+1,b+tot+1);
        rep(i,1,tot){
            if(b[i].s==-1) pre--;
            else pre++;
            ans2=max(ans2,pre);
        }
        printf("%d %d
    ",ans1,ans2);
        return 0;
    }

    F .Pizza Delivery

    题意:给定N点M边有向带权图,起点S=1,终点T=2; 对于每个边,问他转向后,起点到终点的最短路变大还是变小或者不变。

    思路:首先肯定要两次SPFA,求出S和T到每个点的最短路,分别是dis1,dis2;

    当且仅当,然后如果dis1[v]+dis2[u]+w[i]<dis1[T],那么这条边可以让最短路变小。

    否则,最短路变大或者不变,如果不变,说明最短路不是必经这条边。

    那么本题的关键问题就是问边是否是最短路必经边。

    我们把最短路上的边抽出来(就是满足dis1[u]+dis2[v]+w[i]==dis1[T]那些有向边,把它看成无向边),然后不难想到就是求“桥”。

    如果桥转向了,那么最短路一定变长。

    #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=200010;
    const ll inf=1LL<<50;
    struct dijst
    {
        struct in{
            ll dis;int u;
            in(){}
            in(ll d,int uu):dis(d),u(uu){}
            bool friend operator<(in w,in v){
                return w.dis>v.dis;
            }
        };
        ll dis[maxn];  int Len[maxn],cnt,S;
        int  Laxt[maxn],Next[maxn],inq[maxn],To[maxn];
        void init(int N){
            cnt=0; rep(i,1,N) inq[i]=Laxt[i]=0,dis[i]=inf;
        }
        void add(int u,int v,int w){
            Next[++cnt]=Laxt[u]; Laxt[u]=cnt;
            To[cnt]=v; Len[cnt]=w;
        }
        void SPFA()
        {
            dis[S]=0;  priority_queue<in>q;
            q.push(in(0LL,S));
            while(!q.empty())
            {
                int u=q.top().u; q.pop(); inq[u]=0;
                for(int i=Laxt[u];i;i=Next[i]){
                    int v=To[i];
                    if(dis[v]>dis[u]+Len[i]){
                        dis[v]=dis[u]+Len[i];
                        if(!inq[v]) inq[v]=1,q.push(in(dis[v],v));
                    }
                }
            }
        }
    }D1,D2;
    int a[maxn],b[maxn],c[maxn],cnt;
    int dfn[maxn],low[maxn],times,Br[maxn];
    int Laxt[maxn],Next[maxn],To[maxn],id[maxn];
    void add(int u,int v,int p)
    {
        Next[++cnt]=Laxt[u]; Laxt[u]=cnt;
        To[cnt]=v; id[cnt]=p;
    }
    void tarjan(int u,int fa)
    {
        dfn[u]=low[u]=++times;
        for(int i=Laxt[u];i;i=Next[i]){
            int v=To[i];
            if(!dfn[v]){
                tarjan(v,u);
                low[u]=min(low[u],low[v]);
                if(low[v]>dfn[u]) Br[id[i]]=1;
            }
            else if(v!=fa) low[u]=min(low[u],dfn[v]);
        }
    }
    int main()
    {
        int N,M;
        scanf("%d%d",&N,&M);
        D1.init(N); D2.init(N);
        D1.S=1; D2.S=2;
        rep(i,1,M) {
           scanf("%d%d%d",&a[i],&b[i],&c[i]);
           D1.add(a[i],b[i],c[i]);
           D2.add(b[i],a[i],c[i]);
        }
        D1.SPFA(); D2.SPFA(); ll Dis=D1.dis[2];
        rep(i,1,M){
            if(D1.dis[a[i]]+D2.dis[b[i]]+c[i]==Dis){
                add(a[i],b[i],i);
                add(b[i],a[i],i);
            }
        }
        rep(i,1,N) if(!dfn[i]) tarjan(i,0);
        rep(i,1,M){
            if(D1.dis[b[i]]+D2.dis[a[i]]+c[i]<Dis) printf("HAPPY
    ");
            else if(Br[i]) printf("SAD
    ");
            else printf("SOSO
    ");
        }
        return 0;
    }
  • 相关阅读:
    挂载在snap的/dev/loop占用100%问题
    机器学习3- 一元线性回归+Python实现
    机器学习-2 模拟评估与选择
    机器学习-1 绪论
    Java面试系列第4篇-HashMap相关面试题
    Java面试系列第3篇-类的加载及Java对象的创建
    Java面试系列第2篇-Object类中的方法
    Java面试系列第1篇-基本类型与引用类型
    第3篇-如何编写一个面试时能拿的出手的开源项目?
    第2篇-如何编写一个面试时能拿的出手的开源项目?
  • 原文地址:https://www.cnblogs.com/hua-dong/p/10371832.html
Copyright © 2011-2022 走看看