hbx的毒瘤贪心系列题解

毒瘤hbx的贪心专题系列题解
A Maximal gcd
  题意:现在给定一个正整数 n。你需要找到 k 个严格递增的正整数a1,?a2,?...,?ak,满足他们的和等于 n 并且他们的最大公因数尽量大。如果不可能请输出 -1。\(1\leq n,k \leq 10^{10}\)
  题解:把 n 的所有因子找出来后,求最大因子 x 满足\(x* \frac {k* (k+1)}{2}\leq n\)即可。序列就是\(1* x,2* x,...,(k-1)* x,n-x* \frac{k* (k-1)}{2}\)
  注意判断时会爆long long!
  复杂度:\(O(\sqrt n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll n,k,tmp,tp,sum,fac[5005];
int faccnt;
inline bool check(ll x)
{
    return x<=(2*n/k)/(k+1);//!!!
}
int main()
{
    scanf("%lld%lld",&n,&k);
    sum=n;
    if(!check(1))
    {
        puts("-1");
        return 0;
    }
    for(register ll i=1;i*i<=n;++i)
    {
        if(n%i) continue;
        if(check(i)) tmp=max(tmp,i);
        if(check(n/i)) tmp=max(tmp,n/i);
    }
    for(int i=1;i<k;++i)
        printf("%lld ",1ll*i*tmp),sum-=i*tmp;
    printf("%lld\n",sum);
    return 0;
}

  B Arthur and walls
  题意:给出一个n* m的矩阵,里面有“*”和“.”两种符号,要求把最少的“*”变成“.”,使得“.”的联通块构成一个矩形。求最少需要变几个“*”。\(1\leq n,m \leq 2000\)
  题解:如果某个2* 2的方块里只有一个“*”则把这个“*”变掉。bfs即可。
  复杂度:\(O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
#define maxn 2005
int G[maxn][maxn],b[5];
char s[maxn][maxn];
int n,m;
struct Node
{
    int x,y;
    Node(){}
    Node(int a,int b):x(a),y(b){}
};
queue<Node> q;
inline void work(int x,int y)
{
    if(G[x][y])
        G[x][y]=0,q.push(Node(x,y));
}
inline void bfs()
{
    while(!q.empty())
    {
        int x=q.front().x,y=q.front().y;
        q.pop();
        b[1]=b[2]=b[3]=b[4]=0;
        if(x!=1&&y!=1) b[1]=G[x-1][y-1]+G[x-1][y]+G[x][y-1];
        if(x!=1&&y!=m) b[2]=G[x-1][y]+G[x-1][y+1]+G[x][y+1];
        if(x!=n&&y!=1) b[3]=G[x][y-1]+G[x+1][y-1]+G[x+1][y];
        if(x!=n&&y!=m) b[4]=G[x][y+1]+G[x+1][y]+G[x+1][y+1];
        if(b[1]==1)
            work(x-1,y-1),work(x-1,y),work(x,y-1);
        if(b[2]==1)
            work(x-1,y),work(x-1,y+1),work(x,y+1);
        if(b[3]==1)
            work(x,y-1),work(x+1,y-1),work(x+1,y);
        if(b[4]==1)
            work(x,y+1),work(x+1,y),work(x+1,y+1);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)
    {
        scanf("%s",s[i]+1);
        for(int j=1;j<=m;++j)
        {
            if(s[i][j]=='.') q.push(Node(i,j));
            else G[i][j]=1;
        }
    }
    bfs();
    for(int i=1;i<=n;++i)
    {
        for(int j=1;j<=m;++j)
        {
            if(G[i][j]==1) cout<<"*";
            else cout<<".";
        }
        puts(" ");
    }
    return 0;
}

  C Student‘s Revenge
  题意:有一个主席每天要处理繁重的事务,但学生们仍然对他非常反感。现在有 n 个任务,学生们会选出 p 个,在这其中主席会选出 k 个来完成,剩下的 n?k 个不会完成。
  完成一项任务会使主席的头发变白\(a_{i}\),不完成就会使学生们的不满意度增加\(b_{i}\)。主席会使\(\sum{b_{i}}\)尽量小,在此基础上使\(\sum{a_{i}}尽量小\)。但是学生们想要使\(\sum{a_{i}}\)尽量大,在此基础上使\(\sum{b_{i}}\)尽量大。
  求学生会选哪 p 个以及主席会选哪 k 个。
  输出时先输出学生选且主席不选的 p-k 个,再输出主席选了的 k 个。按编号大小顺序输出。
  \(1\leq k \leq p \leq n \leq 10^5,1\leq a_{i},b_{i}\leq 10^9\)
  题解:若给定 p 个任务,则主席必然先按 b 降序再按 a 升序排序依次解决。所以反推一下先按 b 升序再按 a 降序的前 p-k 个肯定不会选上。所以先把 n 个中的前 p-k 个去掉(标记不选即可)。
  其次我们要选 k 个 a 最大的和 p-k 个 b 最大的。为了让主席只选那k个,必须有前k个的b值都大于后面p-k个的b值。具体实现看代码吧。
  复杂度:\(O(n\log n)\)

#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 100005
struct Things
{
    int a,b,id,state;
}thi[maxn];
int n,p,k,vis[maxn],cnt,num;
inline bool cmp1(Things x1,Things x2)
{
    if(x1.b!=x2.b) return x1.b<x2.b;
    if(x1.a!=x2.a) return x1.a>x2.a;
    return x1.state<x2.state;
}
inline bool cmp2(Things x1,Things x2)
{
    if(x1.a!=x2.a) return x1.a>x2.a;
    return x1.b>x2.b;
}
int main()
{
    scanf("%d%d%d",&n,&p,&k);
    for(int i=1;i<=n;++i)
        scanf("%d%d",&thi[i].a,&thi[i].b),thi[i].id=i;
    sort(thi+1,thi+n+1,cmp1);
    for(int i=1;i<=p-k;++i) thi[i].state=1;//扔后面去
    sort(thi+1,thi+n+1,cmp2);
    for(int i=1;cnt<k;++i)
        if(!thi[i].state)
        {
            ++cnt;
            vis[thi[i].id]=1;
            thi[i].state=2;//同上
            printf("%d ",thi[i].id);
        }
    sort(thi+1,thi+n+1,cmp1);
    cnt=0;
    for(int i=n;num<p-k;--i)//从后往前扫
    {
        if(cnt>=k)
        {
            ++num;
            printf("%d ",thi[i].id);
        }
        if(vis[thi[i].id]) ++cnt;
    }
    return 0;
}

  D Ball coloring
  题意:有n个数对,可以将数对中的两个数分别放入 l 堆和 r 堆中。求\(min((R_{max}-R_{min})* (L_{max}-L_{min}))\)
  \(1\leq n \leq 200000,1\leq num\leq 10^9\)
  题解:设\(Min,Max\)为全局最大(小)值。
  1):若Min,Max不在同一堆中:把所有较小数丢到Min堆,较大数丢入Max堆。
  2):若在同一堆中:我们需求出\(min(R_{max}-R_{min})\)。令x为数对较小值,y为数对较大值。按x排序。依次交换x,y并更新答案。
  注意:如果Min,Max在同一数对中可跳过2)。
  复杂度:\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
struct Card
{
    int x,y;
    inline friend bool operator < (Card a,Card b)
        {
            if(a.x==b.x) return a.y<b.y;
            return a.x<b.x;
        }
}card[maxn];
int Rmax,Rmin,Bmax,Bmin,maxpos,minpos;
int main()
{
    int n;
    scanf("%d",&n);
    if(n==1)
    {
        puts("0");
        return 0;
    }
    for(int i=1;i<=n;++i)
    {
        scanf("%d%d",&card[i].x,&card[i].y);
        if(card[i].x>card[i].y) swap(card[i].x,card[i].y);
    }
    sort(card+1,card+n+1);
    int maxy=card[1].y,minx=card[1].x;
    for(int i=1;i<=n;++i)
    {
        if(card[i].x<=minx&&card[i].y>=maxy)
        {
            maxpos=minpos=i;
            minx=card[i].x,maxy=card[i].y;
        }
        else if(card[i].x<minx)
        {
            minpos=i;
            minx=card[i].x;
        }
        else if(card[i].y>maxy)
        {
            maxpos=i;
            maxy=card[i].y;
        }
    }
    Rmax=maxy,Bmin=minx;//全局最大最小
    Rmin=card[minpos].y,Bmax=card[maxpos].x;
    for(int i=1;i<=n;++i)
    {
        Rmin=min(Rmin,card[i].y);
        Bmax=max(Bmax,card[i].x);
    }
    long long ans=1ll*(Rmax-Rmin)*(Bmax-Bmin);//第一种情况
    if(maxpos!=minpos)//第二种情况
    {
        Bmax=maxy,Bmin=minx;
        Rmax=max(card[n].x,card[1].y);
        int premin=card[1].y;
        Rmin=min(card[1].y,card[2].x);
        int tmp=Rmax-Rmin;
        for(int i=2;i<n;++i)
        {
            Rmax=max(card[i].y,Rmax);
            Rmin=min(min(card[i].y,premin),card[i+1].x);
            premin=min(premin,card[i].y);
            if(Rmax-Rmin<tmp) tmp=Rmax-Rmin;
        }
        ans=min(ans,1ll*tmp*(Bmax-Bmin));
    }
    printf("%lld\n",ans);
    return 0;
}

  E Ant man
  题意:有 n 个点,每个点有 x,a,b,c,d 五个属性。从 i 到 j 的距离定义为
  \begin{cases}
\mid x_{i}-x_{j} \mid+c_{i}+b_{j}, & x_{i}>x_{j} \newline
\mid x_{i}-x_{j} \mid+d_{i}+a_{j}, & x_{j}>x_{i}
\end{cases}
  给定起点终点,求经过每个点恰好一次的最短路。
  \(n\leq 5000,1\leq x,a,b,c,d \leq 10^9\)
  保证 x,a,b,c,d 都是严格单调递增的。
  题解:直接在区间中插入,维护一个链表。
  复杂度:\(O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
struct Point
{
    long long x,a,b,c,d;
}poi[5005];
int n,s,e,nex[5005],tmppos;
long long ans,cost,tmpcost;
inline long long dist(int x,int y)
{
    Point a=poi[x],b=poi[y];
    if(b.x<a.x) return a.x-b.x+a.c+b.b;
    return b.x-a.x+a.d+b.a;
}
int main()
{
    scanf("%d%d%d",&n,&s,&e);
    for(int i=1;i<=n;++i) scanf("%lld",&poi[i].x);
    for(int i=1;i<=n;++i) scanf("%lld",&poi[i].a);
    for(int i=1;i<=n;++i) scanf("%lld",&poi[i].b);
    for(int i=1;i<=n;++i) scanf("%lld",&poi[i].c);
    for(int i=1;i<=n;++i) scanf("%lld",&poi[i].d);
    nex[s]=e;
    ans+=dist(s,e);
    for(int i=1;i<=n;++i)
    {
        if(i==s||i==e) continue;
        cost=1e18;
        for(int j=s;j!=e;j=nex[j])
        {
            tmpcost=dist(j,i)+dist(i,nex[j])-dist(j,nex[j]);
            if(cost>tmpcost)
            {
                cost=tmpcost;
                tmppos=j;
            }
        }
        ans+=cost;
        nex[i]=nex[tmppos];
        nex[tmppos]=i;
    }
    printf("%lld\n",ans);
    return 0;
}


以上为考试题目。



  F New Year Snowman
  题意:给定\(r_{i}\),求元素互不相同的三元组最多有多少个。\(1\leq n\leq 5* 10^5,r_{i} \leq 10^6\)
  题解:每次把剩余最多的三个拿出来即可。
  复杂度:\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define maxn 100005
int n,cnt,tmp[maxn],anscnt,t1,t2,t3;
struct Ball
{
    int size,num;
    inline friend bool operator < (Ball a,Ball b)
        {
            if(a.num==b.num) return a.size<b.size;
            return a.num<b.num;
        }
}ball[maxn],tmpa,tmpb,tmpc;
struct Ans
{
    int t1,t2,t3;
}ans[maxn];
priority_queue<Ball> q;
inline void func(Ball x)
{
    if(x.num>1) q.push((Ball){x.size,--x.num});
    else --cnt;
}
inline void work()
{
    tmpa=q.top(),q.pop();
    tmpb=q.top(),q.pop();
    tmpc=q.top(),q.pop();
    t1=tmpa.size,t2=tmpb.size,t3=tmpc.size;
    if(t1<t2) swap(t1,t2);
    if(t1<t3) swap(t1,t3);
    if(t2<t3) swap(t2,t3);
    ans[++anscnt]=(Ans){t1,t2,t3};
    func(tmpa),func(tmpb),func(tmpc);
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
        scanf("%d",&tmp[i]);
    sort(tmp+1,tmp+n+1);
    for(int i=1;i<=n;++i)
    {
        if(tmp[i]!=tmp[i-1])
            ball[++cnt].size=tmp[i],ball[cnt].num=1;
        else ++ball[cnt].num;
    }
    for(int i=1;i<=cnt;++i) q.push(ball[i]);
    while(cnt>=3)
        work();
    printf("%d\n",anscnt);
    for(int i=1;i<=anscnt;++i)
        printf("%d %d %d\n",ans[i].t1,ans[i].t2,ans[i].t3);
    return 0;
}

  G 南园满地堆轻絮
  题意:对于正整数数列\(a_{i}\)和\(b_{i}\), 且b序列非严格单调递增, 使得\(max(\mid a_{i}-b_{i}\mid)\)尽量小。给定\(a_{i}\)。
\(n\leq 5* 10^6\)
  题解:画一个\(a_{i}\)折线图可以发现答案为最大的逆序对的差除二向上取整。当然二分也可以(虽然我不知道为什么带了一个log跑的比没带log还快一些)。
  复杂度:\(O(n)\)

#include<bits/stdc++.h>
using namespace std;
long long a[5000005],sa,sb,sc,sd,mod;
int n;
inline long long mul(long long a,long long b)
{
    return a*b%mod;
}
inline long long func(long long x)
{
    return (mul(sa,mul(x,mul(x,x)))+mul(sb,mul(x,x))+mul(sc,x)+sd)%mod;
}
inline void pre()//生成数据的
{
    scanf("%d%lld%lld%lld%lld%lld%lld",&n,&sa,&sb,&sc,&sd,&a[1],&mod);
    for(int i=2;i<=n;++i)
        a[i]=(func(a[i-1])+func(a[i-2]))%mod;
}
int main()
{
    pre();
    long long ans=-1e18,maxn=-1e18;
    for(int i=1;i<=n;++i)
    {
        if(maxn>a[i]) ans=max(ans,(maxn-a[i]+1)>>1);
        else maxn=a[i];
    }
    printf("%lld\n",ans);
    return 0;
}

  H Pavel and Triangles
  题意:有 n 种木棒,第 i 种的长度是\(2^{i-1}\)。给定每种木棒的数量\(a_{i}\),求最多能组成多少个三角形。
  \(1\leq n\leq 3* 10^5,a_{i}\leq 10^9\)
  题解:从前往后扫,优先组等腰,还有多就组等边。
  复杂度:\(O(n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[300005];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%lld",&a[i]);
    ll ans=a[1]/3,num;
    a[1]%=3;
    ll res=a[1];
    for(int i=2;i<=n;++i)
    {
        num=min(res,a[i]/2);
        res-=num;
        ans+=num;
        a[i]-=num*2;
        ans+=a[i]/3;
        res+=a[i]%3;
    }
    printf("%lld",ans);
    return 0;
}

  I Nauuo and Cards
  题意:你的手上有 n 张牌,牌堆中有 n 张牌,共有 n 张 0 牌,和 n 张数字牌(从 1 到 n )。定义一次操作为将手中的牌放到牌堆的底部,并把牌堆顶端的牌拿到手中,求使用最少的操作次数能够让牌堆中的牌变为\(1\sim n\)的有序序列。
  题解:如果1号牌在手上,则直接一个个先收再打即可。每张牌位置为\(pos_{i}\),代价为\((pos[i]+1)+(n-i)\),也就是收牌加打出牌。取max即可。如果一号牌在牌堆里,则看能否形成从\(pos[1]\sim n\),\(1\sim k\)的序列。如果有这样的序列则显然更优。
  复杂度:\(O(n)\)

#include<cstdio>
using namespace std;
#define maxn 200005
int a[maxn], b[maxn], pos[maxn], ans;
inline int max(int a, int b)
{
    return a > b ? a : b;
}
int main()
{
    int n, i;
    scanf("%d", &n);
    for (i = 1; i <= n; ++i) scanf("%d", &a[i]), pos[a[i]] = 0;
    for (i = 1; i <= n; ++i) scanf("%d", &b[i]), pos[b[i]] = i;
    for (i = 1; i <= n; ++i) ans = max(ans, pos[i] - i + n + 1);
    if (pos[1])
    {
        for (i = 2; pos[i] == pos[1] + i - 1; ++i);
        if (pos[i - 1] == n)
        {
            int j;
            for (j = i; j <= n && pos[j] <= j - i; ++j);
            if (j > n)
            {
                printf("%d\n", n + 1 - i);
                return 0;
            }
        }
    }
    printf("%d\n", ans);
    return 0;
}

  J Match Points
  题意:给定数列\(x_{i}\),若\(z\leq \mid x_{i}-x_{j}\mid\),则称\(x_{i},x_{j}\)能匹配上。
  求最多能配对多少组。\(2\leq n\leq 2* 10^5,1\leq z,x_{i}\leq10^9\)
  题解:二分。前mid个和后mid个依次匹配即可。
  复杂度:\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define maxn 200005
int n,z,pos[maxn];
inline bool check(int x)
{
    for(int i=1;i<=x;++i)
        if(abs(pos[i]-pos[n-x+i])<z) return false;
    return true;
}
int main()
{
    scanf("%d%d",&n,&z);
    for(int i=1;i<=n;++i) scanf("%d",&pos[i]);
    sort(pos+1,pos+n+1);
    int l=0,r=(n>>1),mid,ans;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(mid)) l=mid+1,ans=mid;
        else r=mid-1;
    }
    printf("%d\n",ans);
    return 0;
}

  K Artem and Array
  题意:给定序列\(a_{i}\),每删去一个数可获得左边一个的数与右边一个的数的最小值的分数。求分数最大值。\(1\leq n\leq 5* 10^5,1\leq a_{i}\leq 10^6\)
  题解:先删去中间小两边大的(单调栈),在排序删去除最后两个之外的。
  复杂度:\(O(n\log n)\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll a[600005], ans;
int n, top, x;
int main()
{
    scanf("%d", &n);
    while (n--)
    {
        scanf("%d", &x);
        while (top && a[top] <= x && a[top] <= a[top - 1])
            ans += min(a[--top], x * 1ll);
        a[++top] = x;
    }
    sort(a + 1, a + top + 1);
    for (int i = 1; i <= top - 2; ++i) ans += a[i];
    printf("%lld", ans);
    return 0;
}

  L Beijing Guards
  题意:n 个人形成环。每个人所收到的礼品和他两旁的人都不能有一样的。问最多需要准备多少种礼品。每个人需要\(a_{i}\)个礼品。\(1\leq n\leq 10^5\)
  题解:如果 n 为偶数则直接取\(max(a_{i}+a_{i+1})\)即可。否则二分。设\(a_{1}\)为左右分界线。若 i 为奇数则尽量往左取否则往右取。最后看第 n 个是否在左边取过即可。
  注意 n=1 时要直接输出。
  复杂度:\(O(n\log n)\)

#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 100005
int n, a[maxn], cl[maxn], cr[maxn];
long long l, r;
inline bool check(long long x)
{
    cl[1] = a[1];
    for (int i = 2; i <= n; ++i)
    {
        if (i & 1)
        {
            cr[i] = min(0ll + a[i], x - a[1] - cr[i - 1]);
            cl[i] = a[i] - cr[i];
        }
        else
        {
            cl[i] = min(a[i], a[1] - cl[i - 1]);
            cr[i] = a[i] - cl[i];
        }
    }
    return !cl[n];
}
int main()
{
    while (scanf("%d", &n) && n)
    {
        l = r = 0;
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), r += a[i];
        if (n == 1)
        {
            printf("%d\n", a[1]);
            continue;
        }
        a[n + 1] = a[1];
        for (int i = 1; i <= n; ++i) l = max(l, 0ll + a[i] + a[i + 1]);
        if (!(n & 1))
        {
            printf("%lld\n", l);
            continue;
        }
        while (l <= r)
        {
            long long mid = (l + r) >> 1;
            if (check(mid)) r = mid - 1;
            else l = mid + 1;
        }
        printf("%lld\n", l);
    }
    return 0;
}

  M Moving Tables
  题意:有一条走廊,每次只能通过一张桌子。在任意两个房间间搬桌子都要10分钟。给定n个桌子以及起点终点,求最多要多少分钟搬完。同一时刻可以搬多张桌子。400间房间,\(n\leq 200\)
  题解:将搬动区间加10再最后取max。
  复杂度:\(O(n^2)\)

#include<bits/stdc++.h>
using namespace std;
int cnt[405];
int main()
{
    int t, n, st, ed, ans;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d", &n);
        memset(cnt, 0, sizeof(cnt));
        while (n--)
        {
            scanf("%d%d", &st, &ed);
            if (st > ed) swap(st, ed);
            if (!(st & 1)) --st;
            if (ed & 1) ++ed;
            for (int i = st; i <= ed; ++i) cnt[i] += 10;
        }
        ans = 0;
        for (int i = 1; i <= 400; ++i) ans = max(ans, cnt[i]);
        printf("%d\n", ans);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/123789456ye/p/11517487.html

时间: 2024-10-09 12:34:28

hbx的毒瘤贪心系列题解的相关文章

HDU 1661 Assigments 贪心法题解

Problem Description In a factory, there are N workers to finish two types of tasks (A and B). Each type has N tasks. Each task of type A needs xi time to finish, and each task of type B needs yj time to finish, now, you, as the boss of the factory, n

【ZROI 537】贪心题 题解

[ZROI 537]贪心题 题解 Link Solution 最大的一边直接放到一起贪心即可 着重讲小的一边 已知对于二分图匹配,其答案即为最大流 令时间集合为 \(T = {1,2,3,\dots,maxt}\) 对于每一门课程,按照如下方式建图: 每个任务为一个点,每个时间为一个点,每个任务向其对应的时间区间连边,源点向每个任务连边,边权为 \(1\),每个时间向汇点连边,边权为 \(1\) 考虑第一门课程: 我们选择一些时间节点分给它,设为 \(T_1\) 假设最大流中任务集合为 \(A\

杭电多校HDU 6586 String(序列自动机 贪心)题解

题意: 给你一个串,现需要你给出一个子序列,满足26个约束条件,\(len(A_i) >= L_i\) 且 \(len(a) <= R_i\), \(A_i\)为从a到z的26个字母. 思路: 先用序列自动机(?)构造出某个位置后每个字母的个数,每个字母 的第一个位置. 然后每次贪心地加入最小的字符,加入的条件为当前字母加入后,后面的字符满足剩余的条件. 即剩余的字母在不超R_i的情况下能构成k长度的串,剩余的字母\(A_i+\)已拿取字母\(A_i >= L_i\)且满足\(L_i\)

Heoi2014系列题解

Bzoj3609人人尽说江南好 显然我们要聚集起一个大小为m的石堆需要m - 1次的合并操作,我们可以把贡献单独拿出来看,我们将场上所有石子移动到无法移动的状态步数一定和把所有石子依次合并至上限的次数一样,因为...此处省略一千言.. 大概意会一下吧,感觉不好言传...大概是每次合并贡献实际是相同的这种,就像你算$x_1*x_2*x_3*...*x_n$的值一样,你没有办法通过改变乘的顺序减少乘的次数. 所以直接算出需要多少步,判一判奇偶输出答案. 代码 : #include<bits/stdc

HLJU14级贪心训练题解

由于有的题是很久之前写的题解(主要是我太懒了~~~),所以这里就不从新写了,直接给大家链接了^_^ A--最少拦截系统 题解链接:最少拦截系统 B--今年暑假不AC 题解链接:今年暑假不AC C--Tian Ji -- The Horse Racing 题解链接:Tian Ji -- The Horse Racing D--Max Sum 题解链接:Max Sum PS:有问题的,可以在群里讨论,或者是通过QQ问我,附上本弱QQ:1426137347   ^_^

ZOJ 3963 Heap Partition(multiset + stl自带二分 + 贪心)题解

题意:给你n个数字s1~sn,要你把它们组成一棵棵二叉树,对这棵二叉树来说,所有节点来自S,并且父节点si<=子节点sj,并且i<j,问你树最少几棵二叉数.树 思路:贪心.我们往multiset加还能加子节点的节点,二分查找一个个大于等于当前插入节点的节点,然后插入,若找不到则重新建一棵树. 没想到set自带lower_bound(),第一次迭代器遍历TLE就想着手动写二分...然后发现自带二分... 代码: #include<iostream> #include<stdio

UVA 10382 Watering Grass(区间覆盖,贪心)题解

题意:有一块草坪,这块草坪长l 米,宽 w 米,草坪有一些喷头,每个喷头在横坐标为 p 处,每个喷头的纵坐标都是(w/2) ,并且喷头的洒水范围是一个以喷头为圆心,半径为 r 米的圆.每次最少需要打开多少个喷头来给草坪洒水,并且草坪各处都能被洒到,不行输出-1 思路:这是一道区间覆盖(贪心)题: 有一堆区间 l1, r1:l2, r2...ln,rn,问你最少用几个能覆盖0~P的长度 那么我们先按照L升序排序,far是目前所能找到的最远处,R是上一次查询所能找到的最远处,每次查询我们都要找后面满

贪心策略 题解(合集)

背包问题[DP] 有一个背包,背包容量是M=150kg.有7个物品,物品不可以分割成任意大小.要求尽可能让装入背包中的物品总价值最大,但不能超过总容量. 01背包 f[j]=max(f[j],f[j-w[i]]+c[i]); 搬书[DP] 陈老师桌上的书有三堆,每一堆都有厚厚的一叠,你想逗一下陈老师,于是你设计一个最累的方式给他,让他把书拿下来给同学们.若告诉你这三堆分别有i,j,k本书,以及每堆从下到上书的质量,每次取书只能从任一堆的最上面取,显然,每次取书陈老师的体力消耗都会加大,这里用体力

SPOJ_QTREE系列题解

QTREE4 #pragma comment(linker, "/STACK:102400000,102400000") //#include<bits/stdc++.h> #include <ctime> #include <iostream> #include <assert.h> #include <vector> #include <queue> #include <cstdio> #inclu