2021.9.12 Week Race (Greed + Priority Queue + Binary Answer)

Catalog

Array Splitting (Differential + Greedy)

Selfish Grazing

Missile Interception (Greedy)

Operating System (Priority Queue + Greed)

Brownie Slicing (Binary Answer + Matrix Prefix and)

Array Splitting (Differential + Greedy)

Topic:

Give you a n array of a, with n numbers, arranged from smallest to largest. Break the array into k segments so thatMinimum, output this value.

Ideas:

      1 2 3  4  5  6
a[i]: 4 8 15 16 23 42    //Original Array
c[i]: 4 7 1  7  19      //Difference array

1. Divide into k segments, each of which (max(i)-min(i)) equals the sum of the differences between the zones.
Example: If a[3],a[4],a[5] is divided into a paragraph, 23-15=8 is equivalent to c[3]+c[4]=1+7=8.

2. RequestMinimum, then keep the difference as small as possible, and let the difference be large for its own group (Maximum-Minimum==0 for its own group). So sort the C array.

3. The maximum is divided into sections, a[n]-a[1];

Now you want to divide it into k segments, subtract the largest k-1 from the C array, and make them one element segment.

sum=a[n]-a[1];
for(int i=n-1;i>n-k;i--)
   sum-=c[i];

AC code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx=3e5+10;
int a[maxx];
int c[maxx];
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1; i<=n; i++)
        cin>>a[i];
    if(k==1)
    {
        cout<<a[n]-a[1]<<endl;
    }
    else
    {
        for(int i=2; i<=n; i++)
        {
            c[i-1]=a[i]-a[i-1];
        }
        sort(c+1,c+n);
        int sum=a[n]-a[1];
         for(int i=n-1;i>n-k;i--)
         sum-=c[i];
        cout<<sum<<endl;
    }
}

Selfish Grazing

Topic:

Given the left and right endpoints (l and r) of n segments, the maximum number of disjoint segments in N segments is output.

Ideas:

Sort the right endpoints of each segment, small first and large last. Traverse the array if the left endpoint of the current segment is greater than or equal to the right endpoint of the previous segment. The sequence of left and right endpoints of the last multiple segments is an ascending sequence.

AC code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx=50005;
struct node
{
    int l,r;
} a[50005];
bool cmp(node x,node y)
{
    return x.r<y.r;
}
int main()
{
    int n;
    cin>>n;
    for(int i=0; i<n; i++)
    {
        cin>>a[i].l>>a[i].r;
    }
    sort(a,a+n,cmp);
    int t=a[0].r;
    int ans=1;
    for(int i=1;i<n;i++)
    {
        if(a[i].l>=t)
        {
            t=a[i].r;
            ans++;
        }
    }
    cout<<ans<<endl;
}

Missile Interception (Greedy)

Topic:

 

 

Sample input:

0 0 10 0
2
-3 3
10 0

Sample output:

18

Sample explanation:

 

Ideas:

The distance squares of each missile from the first system are calculated, and then the squares of distances are sorted from large to small. From the beginning, the interception of each missile by the second system is enumerated, and the maximum radius of the second system and the minimum value of the answer are updated each time.

AC code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxx=100005;
int a[maxx];
struct node
{
    int x,y,dis;
}p[maxx];
bool cmp(node aa,node bb)
{
    return aa.dis>bb.dis;
}
int main()
{
    int x1,y1,x2,y2;
    int n;
    cin>>x1>>y1>>x2>>y2;
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>p[i].x>>p[i].y;
        p[i].dis=(x1-p[i].x)*(x1-p[i].x)+(y1-p[i].y)*(y1-p[i].y);
    }
    sort(p,p+n,cmp);
    ll r1=p[0].dis,r2=0;
    ll ans=r1+r2;
    ll tt;
    for(int i=1;i<n;i++)
    {
        tt=(x2-p[i-1].x)*(x2-p[i-1].x)+(y2-p[i-1].y)*(y2-p[i-1].y);
        r2=max(r2,tt);
        r1=p[i].dis;
        ans=min(ans,r1+r2);
    }
    cout<<ans<<endl;
}

Operating System (Priority Queue + Greed)

Topic:

Ideas:

1. Priority queue priority_queue<node>q;Priorities are given priority according to the title, but also by arrival time.

bool operator < (const node x,const node y)
{
    if(x.f!=y.f)
        return x.f<y.f;
    else
        return x.da>y.da;
}

2. Use time to record the current time and keep updating the time.

a,b,c,d is new entry node information, current node now

 if(b>=time+now.run)//New entry node arrives late, current node can finish execution
 {
      time+=now.run;
      cout<<now.id<<" "<<time<<endl;
 }
 else//Re-queue the current node if it has a high priority and it will be executed the next time
 {
       now.run=now.run-(b-time);
       q.push(now);
       break;
  }

3. Keep queuing until the queue is empty.

AC code:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct node
{
    ll id,da,run,f;
};
bool operator < (const node x,const node y)
{
    if(x.f!=y.f)
        return x.f<y.f;
    else
        return x.da>y.da;
}
int main()
{
    priority_queue<node>q;
    ll a,b,c,d,time=0;
    while(cin>>a>>b>>c>>d)
    {
         while(!q.empty())
         {
             node now=q.top();
             q.pop();
             if(b>=time+now.run)
             {
                 time+=now.run;
                 cout<<now.id<<" "<<time<<endl;
             }
             else
             {
                 now.run=now.run-(b-time);
                 q.push(now);
                 break;
             }
         }
         node tmp;
         tmp.id=a;tmp.da=b;tmp.run=c;tmp.f=d;
         q.push(tmp);
         time=b;
    }
    while(!q.empty())
    {
          node now=q.top();
          q.pop();
          time+=now.run;
          cout<<now.id<<" "<<time<<endl;
    }
}

Brownie Slicing (Binary Answer + Matrix Prefix and)

Topic:

For square matrix of n<=500 * m<=500, cut a knife A-1 along the horizontal coordinate, then cut each knife B-1 to get a block A*B, and find the maximum value of the minimum sum of the numbers of the block A*B.

 

Ideas:

1. Minimum Maximum=====Binary Answer

2.check function: horizontal cutting A-1 knife, vertical cutting B-1 knife do not affect each other.

(1) Consider dividing the first line into b blocks (> x) first. If not, add the second line and divide it again until you can divide such b blocks. Suppose it is overlaid on line p, then [1,p] will be the first knife for the horizontal cut (i.e., at line p), and then do the same for line p+1. Finally, decide if it can be cut to knife a.
(2) divide rows into b-blocks (> x) using the matrix prefix sum.
 

s=sum[i][j]-sum[fa-1][j]-sum[i][fb-1]+sum[fa-1][fb-1];

AC code:

#include<bits/stdc++.h>
using namespace std;
const int maxx=15100;
typedef long long ll;
int a[505][505];
int sum[505][505];
int R,C,A,B;
bool check(int x)
{
    int fa=1,fb=1;
    int cnta=0,cntb=0;
    int s;
    for(int i=1;i<=R;i++)
    {
        fb=1;
        cntb=0;
        for(int j=1;j<=C;j++)
        {
            s=sum[i][j]-sum[fa-1][j]-sum[i][fb-1]+sum[fa-1][fb-1];
            if(s>=x)
            {
                fb=j+1;
                cntb++;
            }
        }
        if(cntb>=B)
        {
            fa=i+1;
            cnta++;
        }
    }
    if(cnta>=A)
        return true;
    return false;
}
int main()
{
    int l=4005,r=0,mid;
    cin>>R>>C>>A>>B;
    memset(sum,0,sizeof(sum));
    int tt;
    for(int i=1;i<=R;i++)
    {
        tt=0;
        for(int j=1;j<=C;j++)
        {
            cin>>a[i][j];
            r+=a[i][j];
            tt+=a[i][j];
            sum[i][j]=sum[i-1][j]+tt;
            l=min(l,a[i][j]);

        }
    }
    int ans=0;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(check(mid))
        {
            ans=mid;
            l=mid+1;
        }
        else
        {
            r=mid-1;
        }
    }
    cout<<ans<<endl;
}

Tags: Algorithm data structure leetcode

Posted on Tue, 14 Sep 2021 12:02:27 -0400 by antray