# Greedy question set summary

Posted by gurhy on Mon, 13 Sep 2021 04:51:26 +0200

# greedy

## P3817 candy of small A

Meaning:
The sum of two adjacent numbers in the sequence cannot be greater than x. each operation can be - 1. Ask how many operations are carried out at least to make the sequence meet the conditions

Idea:
Start with the first element and then simulate the analysis. cnt record operation times
If a [1] + a [2] > x, we need to subtract one of the numbers. What about subtracting that number—— The first number will only form a pair with the second number, but the second number will also form a pair with the third number, so we operate the second number cnt+=x-a[2]-a[1], which can also reduce the total number of the latter group at the same time.
All the following groups are analogized. We only operate on the second number of each group each time. Record the number of operations

In order to make the operand as small as possible, if a [i] + a [i + 1] > x, we only need to subtract the second number to a[i]+a[i+1]=x, that is, a[i+1]=x-a[i]

```#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=1e5+10;
int n,x,a[N];
int main()
{
cin>>n>>x;
for(int i=1;i<=n;i++) cin>>a[i];
LL cnt=0;
for(int i=1;i<n;i++)
{
LL sum=a[i]+a[i+1]-x;
if(sum>0)
{
cnt+=sum;
a[i+1]=x-a[i];
}
}
cout<<cnt<<endl;
return 0;
}
```

## P5019 [NOIP2018 improvement group] road laying

#### Idea:

Find a [i + 1] > a [i] every time from left to right, and then a[i+1]-a[i] is the number of times that this field becomes 0 before the next maximum number. So every time we find a[i+1]-a[i], cnt+=a[i+1]-a[i]

#### analysis:

It is equivalent to dividing a string into several strings and dividing them with larger numbers.

```6
4 3 2 5 3 5
Split into:
4 3 2
5 3
5
```

We can select an interval [l,r] every time for the number - 1 in the interval. The first large number - 1 will drive the next number - 1, so we only need to process the largest number in the sub segment. If the later smaller number becomes 0 in advance, it is equivalent to reducing the interval [l,r], but it is still the largest number. We are greedy and start from the leftmost to a [i + 1] > a [i] When you operate on a large number, all the following numbers will follow - 1, and the small number in front of each large number is the one that really determines the operand that reduces each large number to 0, so the operation of each large number is a[i+1]-a[i]

```#include <iostream>
#include <algorithm>
using namespace std;

constexpr int N = 1e5 + 100;
int a[N], n;

int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i ++) cin >> a[i];

int sum = 0;
for (int i = 0; i < n; i++)
if (a[i] < a[i + 1]) sum += a[i + 1] - a[i];

cout << sum << '\n';

return 0;
}
```

## E action game

```#include<iostream>
#include<algorithm>
#include <iostream>
#include <utility>
#include <vector>
using namespace std;
typedef pair<int,int> PII;
vector<PII>p,ans;
int main()
{
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int n,t;
cin>>n>>t;
for(int i=0;i<n;i++)
{
int l,r;
cin>>l>>r;
p.push_back({l, r});
}
sort(p.begin(),p.end());

int st=-2e9,ed=-2e9;
for(int i=0;i<p.size();i++)
{
if(p[i].first>=ed)
{
if(st!=-2e9) ans.push_back(make_pair(st,ed));
st=p[i].first,ed=p[i].second;
}
else ed=max(ed,p[i].second);
}
if(ed!=-2e9) ans.push_back({st,ed});

int last=0,flag=1,x=ans[0].first;
for(int i=0;i<ans.size();i++)
{
if((ans[i].second-ans[i].first)>t){ flag=0; break; }
if(last>ans[i].first&&last<ans[i].second)
{
if((last-ans[i].first)<=x) last=ans[i].first;
else {flag=0; break;}
}
x=ans[i].first-last;
last=max(last+t,ans[i].first+t);
}
if(flag) puts("HEIR OF FIRE DESTORYED.");
else puts("YOU DIED.");
return 0;
}
```

Greedy, greedy. It's good to think when you have the right idea. First of all, it is easy to judge that it cannot be established. If it is an even number of elements, judge whether odd and even numbers account for half respectively. If it is an odd number of elements, judge whether odd numbers are 1 more or 1 less than even numbers. If not, output − 1.
Otherwise, we only need to consider two cases

1. The first element is odd.
2. The first element is even.
In other words, our last array must be 10101 or 01010 (1 is regarded as an odd number and 0 as an even number). We can store the odd positions of the current array if the total number of arrays n n If n is an odd number, if there are many odd numbers, put the odd number in the odd position, and if there are few odd numbers, put the odd number in the even position, and then put it in order to calculate the number of moves. If the total number of arrays n n If n is an even number, the odd number is counted once when it is placed in the odd position, and the odd number is counted once when it is placed in the even position. Take m i n min min.
```#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
const int N=1e5+100,INF=0x3f3f3f3f;
int a[N];
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
vector<int>odd;
for(int i=1;i<=n;i++)
{
int c;
cin>>c;
if(c%2) odd.push_back(i);
}
if((n%2==0&&odd.size()*2!=n)||(n%2&&odd.size()*2!=n+1&&odd.size()*2!=n-1))
{
puts("-1");
continue;
}
//if(n==1){puts("0");continue;}

int ans=0;//The number of times an odd number needs to be moved when it is placed in an odd position
int res=0;//The number of times the odd number needs to be moved when it is placed in the even position
if(n%2==0)
{
for(int i=0,k=1;i<odd.size();i++,k+=2)
ans+=abs(odd[i]-k);

for(int i=0,k=2;i<odd.size();i++,k+=2)
res+=abs(odd[i]-k);

ans=min(res,ans);//Take the smallest of the two possibilities as the answer
}else
{
if(odd.size()*2==n+1)
{
for(int i=0,k=1;i<odd.size();i++,k+=2)
ans+=abs(odd[i]-k);
}else
{
for(int i=0,k=2;i<odd.size();i++,k+=2)
ans+=abs(odd[i]-k);
}
}
cout<<ans<<endl;

}
}
```

## P1106 deletion problem

Observe the example and delete the number of a [i] > a [i + 1] each time

Don't forget to remove the leading 0!!!

```#include<iostream>
#include<algorithm>
using namespace std;
const int N=300;
int a[N];
int main()
{
string s;
cin>>s;
int k;
cin>>k;
for(int i=0;i<s.size();i++)
a[i]=s[i]-'0';

int len=s.size();

while(k--)//k times shortening length
{
for(int i=0;i<len-1;i++)
{
if(a[i]>a[i+1])
{
for(int j=i;j<len;j++)//Moving the following number forward is equivalent to deleting this number
a[j]=a[j+1];
break;
}
}
len--;
}

int j=0;
while(len>1&&a[j]==0) j++;//You can't len--, because 0 doesn't count as length

//Output from a place other than the leading 0
for(int i=j;i<len;i++)
cout<<a[i];
puts("");

return 0;
}
```

## P4995 jump!

0, big, small, big, small····

```#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=310;
int h[N];
bool cmp(int a,int b)
{
return a>b;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>h[i];

sort(h+1,h+n+1);

long long sum=0;
int l=0,r=n;
while(l<r)
{
sum+=pow(h[l]-h[r],2);//Jump from small to large (the decimal to the left of the large)
l++;//Move right to the next decimal (the decimal to the right of the big one)
sum+=pow(h[l]-h[r],2);//Then jump from big to small (used twice in the conference)
r--;
}

cout<<sum<<endl;

return 0;
}
```

Topics: Algorithm