Advertisement
Fastrail08

Projects CSES

Jun 22nd, 2025
314
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.91 KB | None | 0 0
  1. #include <bits/stdc++.h>
  2. using namespace std;
  3.  
  4. class triplet{
  5.     public:
  6.     int si, ei;
  7.     long long pi;
  8.    
  9.     triplet(int si, int ei, long long pi){
  10.         this-> si = si;
  11.         this-> ei = ei;
  12.         this-> pi = pi;
  13.     }
  14.    
  15. };
  16.  
  17. bool compare(const triplet &t1, const triplet &t2){
  18.     if(t1.si == t2.si){
  19.         return t1.ei <= t2.ei ? true : false;
  20.     }
  21.     return t1.si < t2.si ? true : false;
  22. }
  23.  
  24. void getMaxProfitByAttendingMeetings(int level, int si, int ei, long long currProfit, long long &maxProfit, vector<triplet> &projects){
  25.     if(level >= projects.size()){
  26.        maxProfit = max(maxProfit, currProfit);
  27.        return;
  28.     }
  29.     //attend
  30.     if(projects[level].ei < si || projects[level].si > ei){
  31.         getMaxProfitByAttendingMeetings(level + 1, min(projects[level].si, si), max(projects[level].ei, ei), currProfit + projects[level].pi, maxProfit, projects);
  32.     }
  33.    
  34.     //don't attend
  35.     getMaxProfitByAttendingMeetings(level + 1, si, ei, currProfit, maxProfit, projects);
  36. }
  37.  
  38. int findNextMeetingThatCanBeAttendedIfIthMeetingAttended(int endTime, int level, vector<triplet> &projects){
  39.     int l = level + 1, r = projects.size() - 1, idx = -1;
  40.     while(l <= r){
  41.         int mid = (r - l) / 2 + l;
  42.         if(projects[mid].si > endTime){
  43.             idx = mid;
  44.             r = mid - 1;
  45.         }
  46.         else{
  47.             l = mid + 1;
  48.         }
  49.     }
  50.     return idx;
  51. }
  52.  
  53. long long getMaxProfitByAttendingMeetingsMemo(int level, vector<triplet> &projects, vector<long long> &memo){
  54.     if(level >= projects.size()){
  55.         return 0;
  56.     }
  57.  
  58.     if(memo[level] != -1){
  59.         return memo[level];
  60.     }
  61.     long long attendedProfit = 0, notAttendedProfit = 0;
  62.    
  63.     /*
  64.     If we are going to attend ith meeting, or the meeting at current level, what is the JUST next meeting that can be attended. Also we can say WHAT LEVEL we GO next if we choose to attend meeting at current level
  65.    
  66.     Generally we jump level + 1 in every case (we take decision of at current level, and the move to next level to take decision of that)
  67.     Here we are also doing the same thing.
  68.    
  69.     If we don't attend the meeting at index 'level' we are not changing the the si or ei, and we can surely attend the next meeting at level + 1, because we didn't attend the meeting at index 'level', as the array is sorted based on start times, the meeting at level + 1 has a start time > meeting at level start time.
  70.    
  71.     If we attend the meeting at index 'level', we are changing the si & ei. We are going to attend this meeting which might BLOCK the meeting at level + 1, level + 2...upto some level + i..
  72.     BLOCK as in if the meeting at index 'level' ends at some duration ei, then all the meetings at next level(upto some level + i) whose start time <= ei are BLOCKED, simply because these meetings will overlap with our ongoing meeting at index 'level'. The meetings that are blocked START at some time during which our current meeting is going on and hence we can't attend those.
  73.    
  74.     So the problem is we can't do level + 1, level + 2(if we attend the meeting)
  75.     Unlike the case where we don't attend the current meeting(where we simply do level + 1), because the meeting[level + 1] is automatically a valid option.
  76.     But If we explore the option to attend current meeting[level] - SO WHAT IS THE FIRST CLOSEST MEETING WHICH START AFTER OUR CURRENT MEETING ENDS or WHAT IS THE FIRST MEETING THAT STARTS JUST AFTER OUR CURRENT MEETING ENDS, essentially making it the first valid meeting that can be attended if we choose to attend the meeting[level].
  77.    
  78.     SO WHAT IS THE FIRST/minimum 'i'/'level + i' where we can jump after we explore the option to attend, first meaning the meeting that has the smallest start time that is atleast larger than the end time of current meeting.  
  79.    
  80.     meeting[level].ei < meeting[level + i].si
  81.    
  82.     [level, level + 1, level + 2, level + 3, level + 4 ....... level + i......] (sorted based on start times)
  83.    
  84.     We explored an option (attend), which means we move to the next level. Here the question is, which level to move to next? As moving to (level + 1) is not going to cut it everytime, as if in case the meeting attended at level might go on even after the meeting[level + 1] starts...or meeting[level + 2]  starts.....making those meetings blocked and impossible to attend to as you can only attend 1 meeting at a time.
  85.    
  86.     We need to move to some level + i, where meeting[level + i].si > meeting[level].ei, i.e. the meeting[level + i] only starts after the meeting[level] ends.
  87.    
  88.     As the array is sorted we can use Binary Search to figure out 'i',as we need to find the meeting whose start time is just larger than the end time of meeting[level]. So whatever 'i' is returned, we move to that level, by calling (level + i).
  89.    
  90.    
  91.    
  92.     */
  93.    
  94.     int nextValidMeetingIdx = findNextMeetingThatCanBeAttendedIfIthMeetingAttended(projects[level].ei, level, projects);
  95.  
  96.     //attend
  97.         attendedProfit = projects[level].pi + getMaxProfitByAttendingMeetingsMemo(nextValidMeetingIdx, projects, memo);
  98.        
  99.     //don't attend
  100.         notAttendedProfit = getMaxProfitByAttendingMeetingsMemo(level + 1, projects, memo);
  101.    
  102.     return memo[level] = max(attendedProfit, notAttendedProfit);
  103. }
  104.  
  105.  
  106. int main() {
  107.     // your code goes here
  108.     int n;
  109.     cin >> n;
  110.     vector<triplet> projects;
  111.     int si, ei;
  112.     long long pi;
  113.     for(int i = 0; i < n; i++){
  114.         cin >> si >> ei >> pi;
  115.         triplet t(si, ei, pi);
  116.         projects.emplace_back(t);
  117.     }
  118.     /*
  119.     Recursive Call
  120.     long long maxProfit = 0;
  121.     getMaxProfitByAttendingMeetings(0, 0, 0, 0, maxProfit, projects);
  122.     cout << maxProfit << '\n';
  123.     */
  124.    
  125.     /*
  126.     Memo Call
  127.     */
  128.     sort(projects.begin(), projects.end(), compare);
  129.     vector<long long> memo(n, -1);
  130.     cout << getMaxProfitByAttendingMeetingsMemo(0, projects, memo) << '\n';
  131. }
  132.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement