突破点1:仔细审题能发现交谈对总是相互挨着,那么一定是横坐标相等纵坐标差一或者纵坐标相等横坐标差一,又发现分割线横线和竖线的数量是给定的,那么这两种线互不干扰,那么从二维转换为一维问题。就用两个数组分别存交谈对数。

突破点2:收集横坐标i和i+1之间有交谈对的数量,纵坐标也是如此,那么最后分别对两个数组贪心找前k个或者前l个最多的交谈对,在其中间有一条竖线或者横线,具体情况具体分析。

突破点3:那么到这里我们发现最后排序完可能丢失了原来的顺序,现在又要按升序输出满足条件的k/l个位置。那么我们在定义vector数组时不能只存交谈对数,还要存原始下标。最后排序先按照交谈对数从大到小满足贪心思想,尽可能多隔开。再对前k/l按照存的原始下标升序排序,最后输出前k/l项即可。

这里时间复杂度为O(m+n+d+logm+logn)。

最后附上代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PII pair<int,int>
//pair<int,int>一个参数是位置下标,另一个是位置的交谈对个数
//这里不以vector下标做索引而单独存一个下标是因为需要排序找到前个k/l个
//最大值后还能根据存的下标保证严格升序

void solve() {
    int n, m, k, l, d;
    cin >> n >> m >> k >> l >> d;
    vector<PII>row(n + 1, {0, 0});
    vector<PII>col(m + 1, {0, 0});
    for (int i = 1; i <= n; i++) {
        row[i].first = i;
    }
    for (int j = 1; j <= m; j++) {
        col[j].first = j;
    }
    while (d--) {
        int x1, y1, x2, y2;
        cin >> x1 >> y1 >> x2 >> y2;
        if (x1 == x2) {
            col[min(y1, y2)].second++;
        } else if (y1 == y2) {
            row[min(x1, x2)].second++;
        }
    }
    //先按照最多的交谈对个数按降序排序
    sort(row.begin() + 1, row.end(), [](PII & a, PII & b) {
        return a.second > b.second;
    });
    sort(col.begin() + 1, col.end(), [](PII & a, PII & b) {
        return a.second > b.second;
    });
    //再按照原下标的大小升序排序,注意这里只排前k/l项!!!
    sort(row.begin() + 1, row.begin()+k+1);
    sort(col.begin() + 1, col.begin()+l+1);
    for(int i=1;i<=k;i++)cout<<row[i].first<<" ";
    cout<<endl;
    for(int i=1;i<=l;i++)cout<<col[i].first<<" ";
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    solve();
    return 0;
}