zoukankan      html  css  js  c++  java
  • 2014多校联合训练第一场(组队训练)

      这是我们第二次组队训练,毕竟经验不足,加上水平不够,导致我们各种被碾压。

      A - Couple doubi:

      这道题是道比较水的数论。但我们都没想出来要怎么做。后来是potaty提议打个表看看,然后lmz打出表后发现了规律。我还没细看,待研究后再补全。

      

      D - Task:

      这道题一看就知道是个贪心(现在只要是有deadline的题我都觉得是贪心了)。虽然想出来了,但还是不会严格证明为什么只要取满足task的且y最小(y相等时x最小)的machine就行了。

      我的做法是把所有machine放进第machine_i_y个桶中,这个桶用set来实现。然后按照x的大小顺序从大到小(x相等时y从大到小)依次取task,每次找到满足最合适的machine。最合适的machine条件上面已经给出(貌似先看x最小,再看y最小也行,不过我的for每个machine再for每个y,如果改成for每个x,时间过不去)。但为什么task是从大到小来取呢?

      题目中钱的公式是500*xi+2*yi,而yi<=100,xi>1。可以发现,只要xi>xj,即xi>=xj+1,那么无论怎么取yi和yj,500*xi+2*yi始终是大于500*xj+2*yj的。所以这样取task能保证钱是最多的。鉴于每个machine只能取一个task,如果不取x(或y)偏大的task,而去取x(或y)较小的task,这明显是一种对money的浪费,而且也没有完成更多的task,所以不会有上述做法的反例存在。综上,上述做法是对的。

      第一次写博客,若有不明白的可以指出,我会尽力解答的。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <queue>
    #include <algorithm>
    #include <set>
    #include <utility>
    #define FOR(i,l,r) for(int i=(l);i<=(r);i++)
    #define FORD(i,r,l) for(int i=(r);i>=(l);i--)
    #define rep(i,n) for(int i=0;i<(n);i++)
    using namespace std;
    typedef long long LL;
    
    pair<int,int> mac[100001],task[100001];
    int n,m;
    int main(){
        while (~scanf("%d%d",&n,&m))
        {
            FOR (i,1,n) scanf("%d%d",&mac[i].second,&mac[i].first);
            sort(mac+1,mac+1+n);
            FOR (i,1,n) swap(mac[i].second,mac[i].first);
            FOR (i,1,m) scanf("%d%d",&task[i].first,&task[i].second);
            sort(task+1,task+1+m);
    
            multiset<int> q[101];
            multiset<int>::iterator it;
            FOR (i,1,n) q[mac[i].second].insert(mac[i].first);
            LL ans=0; int ansgs=0; int j;
            FORD (i,m,1)
            {
                for (j=task[i].second; j<=100; j++)
                {
                    if (!q[j].empty())
                        if ((it=q[j].lower_bound(task[i].first)) != q[j].end())
                            break;
                }
                if (j==101) continue;
                q[j].erase(it);
                ansgs++;
                ans+=500*task[i].first+2*task[i].second;
            }
            /*bool vis[100001];
            FORD (i,m,1)
            {
                FOR (j,1,n)
                    if (mac[j].first>=task[i].first&&mac[j].second>=task[i].second&&!vis[j])
                    {
                        vis[j]=1; ansgs++;
                        ans+=500*task[i].first+2*task[i].second;
                        break;
                    }
            }*/
            cout<<ansgs<<" "<<ans<<endl;
        }
        return 0;
    }
    

      

      F - Shooting:

      这道题苦思良久没想出来,在看了题解之后一下就明白了。说实话,非常佩服出题人,能想出这样的题来。

      题目大意:

      有n个target,每次站在x处射击,最多可以射击k个target。K是由公式K = ( a * Pre + b ) % c算出的,Pre是上一次shooting的得分。具体可参考下图:

      target被射中不会消失。每次的得分是所有被射中的target的距离之和。如果上次的得分大于P,那么这次的得分翻番。求每次的得分。

      解题思路:把距离Di(1<=i<=N)离散化,然后将target按距离从小到大加入函数式线段树中(用左区间点+1,右区间点-1的方式)。然后每次二分一下求出第k个target的位置,二分是利用线段树来算出x处有多少个线段(target)。找到位置之后就很好办了。read得分和read线段的个数的操作是一样的。

      还有种做法是按照X坐标离散化。两种方法本质是差不多的,所以就不赘写了。

      时间复杂度为O(N*logN+2*N*logX+M*(logN*logX+logX)). 感觉3s的时间会不够的样子...

    #include <cstdio>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <cstring>
    #define debug(x) cout<<#x<<" = "<<x<<endl
    #define FOR(i,l,r) for(int i=(l);i<=(r);i++)
    #define rep(i,n) for(int i=0;i<(n);i++)
    #define foreach(it,v) for(__typeof((v).begin()) it=(v).begin();it!=(v).end();it++)
    #define LC(t) ((t)?(t->o[0]):0)
    #define RC(t) ((t)?(t->o[1]):0)
    using namespace std;
    typedef long long LL;
    const int maxn=100001;
    
    int X;
    
    struct btree{
        btree *o[2];
        int cnt;
        LL d;
    }tbt[maxn*50]; int tpo;
    btree *newnode()
    {
        btree *p=&tbt[tpo++];
        p->o[0]=p->o[1]=0;
        p->cnt=p->d=0;
        return p;
    }
    btree *sr(btree *t,int l,int r,int x,int v,int d)
    {
        btree *p=newnode();
        if (t) *p=*t;
        p->cnt+=v; p->d+=d;
        if (l==r) return p;
        int mid=l+r>>1;
        if (x<=mid) p->o[0]=sr(p->o[0],l,mid,x,v,d);
        else        p->o[1]=sr(p->o[1],mid+1,r,x,v,d);
        return p;
    }
    int red1(btree *t,int l,int r,int ll,int rr)
    {
        if (!t) return 0;
        if (ll<=l&&r<=rr) return t->cnt;
        int mid=l+r>>1,ret=0;
        if (ll<=mid) ret+=red1(t->o[0],l,mid,ll,rr);
        if (rr>mid)  ret+=red1(t->o[1],mid+1,r,ll,rr);
        return ret;
    }
    LL red2(btree *t,int l,int r,int ll,int rr)
    {
        if (!t) return 0;
        if (ll<=l&&r<=rr) return t->d;
        int mid=l+r>>1; LL ret=0;
        if (ll<=mid) ret+=red2(t->o[0],l,mid,ll,rr);
        if (rr>mid)  ret+=red2(t->o[1],mid+1,r,ll,rr);
        return ret;
    }
    
    struct target{
        int l,r,d;
        bool operator< (const target &a) const { return d<a.d; }
    }tar[maxn];
    
    int n,m,P;
    btree *bt[maxn];
    
    void init() { tpo=0; X++; }
    int ef(int x,int k)
    {
        int l=1,r=n,mid;
        while (l<=r)
        {
            mid=l+r>>1;
            if (red1(bt[mid],1,X,1,x)<=k) l=mid+1;
            else                          r=mid-1;
        }
        return r;
    }
    int main(){
        for (int x,a,b,c,z;scanf("%d%d%d%d",&n,&m,&X,&P)!=EOF;)
        {
            init();
    
            FOR (i,1,n) scanf("%d%d%d",&tar[i].l,&tar[i].r,&tar[i].d);
            sort(tar+1,tar+1+n);
            FOR (i,1,n)
                bt[i]=sr(bt[i-1],1,X,tar[i].l,1,tar[i].d),
                bt[i]=sr(bt[i],1,X,tar[i].r+1,-1,-tar[i].d);
    
            LL pre=1,ans,k;
            for (int i=1;i<=m;i++,pre=ans)
            {
                scanf("%d%d%d%d",&x,&a,&b,&c);
                k=((LL)a*pre+(LL)b)%c;
                z=ef(x,k);
                ans=red2(bt[z],1,X,1,x);
                if (pre>P) ans*=2;
                printf("%I64d
    ",ans);
            }
        }
        return 0;
    }
    

      

  • 相关阅读:
    sopt:一个简单的python最优化库
    条件GAN论文简单解读
    python PIL 图像处理库简介(一)
    python自动制作gif并添加文字
    github+hexo搭建博客
    haskell简明入门(一)
    DCGAN 代码简单解读
    手机浏览器 H5直播
    js获取网页的宽高
    vue 对象赋值 对象身上已经有了属性,但是视图层并没有更新该数据 问题
  • 原文地址:https://www.cnblogs.com/monmonde/p/3912693.html
Copyright © 2011-2022 走看看