【2021ICPC网络赛】 补个A题 (线段树和STL写法)

image

线段树思路:

  • 要找结束时间小于当前物品开始时间的机器,线段树上维护区间最小值
  • 要找早出现的可行位置,线段树上二分,查询返回尽可能靠左的位置,i-n没有的话1-i再查
  • 找到位置要单点更新
点击查看代码
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <stack>
#include <cstdio>
#include <queue>
#include <set>
#include<sstream>
#include <cstring>
#include <cmath>
#include <bitset>
//#pragma GCC optimize(2);
#define IOS ios::sync_with_stdio(false);
#define mm(a, b) memset(a, b, sizeof(a))
#define il segtree[i].l
#define ir segtree[i].r
#define jl segtree[j].l
#define jr segtree[j].r
const double PI = acos(-1.0);
typedef long long ll;
const int N = 1e5+5;
const int M = N*2;
const double eps =1e-8;
const ll mod =  998244353;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double maxd = -1e9;
const int maxn = 500;
using namespace std;
typedef pair<string,int> PII;
struct SegTree{
    int val;
}segtree[N<<2];
void push_up(int rt){
    segtree[rt].val = min(segtree[rt<<1].val,segtree[rt<<1|1].val);
}
void build(int l,int r,int rt){
    if(l == r) { segtree[rt].val = 0; return ; }
    int mid =l+r>>1;
    build(l,mid,rt<<1); build(mid+1,r,rt<<1|1);
    push_up(rt);
}
int query(int a,int b,int val,int l,int r,int rt){
    if(l==r&&val>=segtree[rt].val){ return l; }
    int mid = l+r>>1;
    int ans = -1;
    if(a<=mid&&val>=segtree[rt].val) ans = query(a,b,val,l,mid,rt<<1);//选的位置尽可能靠左

    if(b>mid&&val>=segtree[rt].val&&ans == -1)  ans = query(a,b,val,mid+1,r,rt<<1|1);
    return ans;
}
void modify(int pos,int val,int l,int r,int rt){
    if(l == r) { segtree[rt].val = val; return; }
    int mid =l+r>>1;
    if(pos<=mid) modify(pos,val,l,mid,rt<<1);
    else modify(pos,val,mid+1,r,rt<<1|1);
    push_up(rt);
}
int cnt[N];
int main(){
    int n,m,a,b;
    cin>>n>>m;
    build(1,n,1);
    int maxx = 0;
    for(int i=1;i<=m;i++){//全部向右偏移一位
        cin>>a>>b;
        int u = i%n;
        if(!u) u = n;
        int t = query(u,n,a,1,n,1);
        if(t!=-1) cnt[t-1]++;
        else{
            t = query(1,u,a,1,n,1);
            if(t == -1) continue;
            cnt[t-1]++;
        }
        modify(t,a+b,1,n,1);
        maxx =max(cnt[t-1],maxx);
    }
    vector<int>ans;
    for(int i=0;i<n;i++)
        if(cnt[i] == maxx) ans.push_back(i);
    for(int i=0;i<ans.size();i++){
        if(i)printf(" ");
        printf("%d",ans[i]);
    }
    return 0;
}

STL思路:

  • 一个堆u放k个机器的编号和它的结束时间
  • 另一个放当前物品能上的机器的编号v
  • 在v上二分找编号
  • 注意物品的起始时间是非递减的
  • 重载小于号时候time相等必须排id
点击查看代码
#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <stack>
#include <cstdio>
#include <queue>
#include <set>
#include<sstream>
#include <cstring>
#include <cmath>
#include <bitset>
//#pragma GCC optimize(2);
#define IOS ios::sync_with_stdio(false);
#define mm(a, b) memset(a, b, sizeof(a))
const double PI = acos(-1.0);
typedef long long ll;
const int N = 1e5+5;
const int M = N*2;
const double eps =1e-8;
const ll mod =  998244353;
const ll INF = 0x3f3f3f3f3f3f3f3f;
const double maxd = -1e9;
const int maxn = 500;
using namespace std;
typedef pair<string,int> PII;
int a[N],b[N];
struct node{
    int id, val;
    bool operator< (const node b)const {
        if(val == b.val) return id<b.id;
        return val<b.val;
    }
};
set<node>u;
set<int> v; int cnt[N]; int maxx;
int main(){
    int k,n;
    cin>>k>>n;
    for(int i=0;i<n;i++)cin>>a[i]>>b[i];
    for(int i=0;i<min(n,k);i++){
        cnt[i]++;maxx =max(maxx,cnt[i]);
        u.insert({i,a[i]+b[i]});
    }
    for(int i = k; i <n;i++){
        while(!u.empty()){
            node top = *u.begin();
            if(top.val<=a[i]) v.insert(top.id),u.erase(u.begin());
            else break;
        }
        if(v.empty())continue;
        int d = i%k;
        auto it = v.lower_bound(d);
        if(it == v.end()) it =v.begin();
        cnt[*it]++;
        maxx =max(maxx,cnt[*it]);
        u.insert({*it,a[i]+b[i]});
        v.erase(it);
    }
    vector<int>ans;
    for(int i=0;i<k;i++)
    if(cnt[i] == maxx) ans.push_back(i);
    for(int i=0;i<ans.size();i++){
        if(i)printf(" ");
        printf("%d",ans[i]);
    }
    return 0;
}
posted @ 2021-09-23 20:16  qingyanng  阅读(58)  评论(1编辑  收藏  举报