链表

数组模拟大法好啊 orz 前向星 + 数组下标搞得各种线段树什么得
邻值查找
STL嚎啊

#include <iostream>
#include <set>
using namespace std;
typedef pair<int, int> P;
const int maxn = 1e5 + 5;
#define int long long

struct node{
    int v, id;
    node(){}
    node(int _v, int _id){
        v = _v, id = _id;
    }
    bool operator < (const node & a) const {
        return v < a.v || (v == a.v && id < a.id);
    }
}a[maxn];
P ans[maxn];
set<node> S;

signed main(){
    int n;
    cin >> n;
    for(int i = 1; i <= n; i++ ){
        cin >> a[i].v;
        a[i].id = i;
        S.insert(a[i]);
    }
    S.insert(node(-2e9, -1)), S.insert(node(2e9, -1));
    for(int i = n; i >= 2; i --) {
        auto p1 = S.lower_bound(a[i]);
        auto p3 = p1;
        p3++;
        int cha = 2e9, pos;
        if((*p3).id != -1) pos = (*p3).id, cha = abs((*p3).v - a[i].v);
        auto p2 = p1;
        p2--;
        if((*p2).id != -1 && cha >= abs((*p2).v - a[i].v)) pos = (*p2).id, cha = abs((*p2).v - a[i].v);
        ans[i] = P(cha, pos);
        S.erase(p1);
    }
    for(int i = 2; i <= n; i ++) cout << ans[i].first << " " << ans[i].second << endl;
    return 0;
}

yxc 老师 写的模拟链表解法

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;
typedef pair<LL, int> PII;
const int N = 100010;

int n;
int l[N], r[N];
int p[N];
PII a[N], ans[N];

int main()
{
    cin >> n;
    for (int i = 1; i <= n; i ++ )
    {
        cin >> a[i].first;
        a[i].second = i;
    }
    sort(a + 1, a + 1 + n);

    a[0].first = -3e9, a[n + 1].first = 3e9;
    for (int i = 1; i <= n; i ++ )
    {
        l[i] = i - 1, r[i] = i + 1;
        p[a[i].second] = i;
    }

    for (int i = n; i > 1; i -- )
    {
        int j = p[i], left = l[j], right = r[j];
        LL left_value = abs(a[left].first - a[j].first);
        LL right_value = abs(a[right].first - a[j].first);
        if (left_value <= right_value) ans[i] = {left_value, a[left].second};
        else ans[i] = {right_value, a[right].second};
        l[right] = left, r[left] = right;
    }

    for (int i = 2; i <= n; i ++ ) cout << ans[i].first << ' ' << ans[i].second << endl;

    return 0;
}
作者:yxc
链接:https://www.acwing.com/activity/content/code/content/29173/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

先上手写堆

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1000000+5;

int heap[maxn];
int siz=0;

void push(int x){
    heap[++siz]=x;
    int cnt=siz;
    while(cnt>1){
        int nxt=cnt>>1;
        if(heap[cnt>>1]>heap[cnt]) swap(heap[cnt>>1],heap[cnt]);
        else break;
        cnt=nxt;
    }
    return ;
}

void pop(){
    swap(heap[siz],heap[1]);
    siz--;
    int cnt=1;
    while((cnt<<1) <= siz){
        int nxt=cnt<<1;
        if((nxt|1)<=siz&&heap[nxt|1]<heap[nxt]) nxt++;// 先换右 写的方便
        if(heap[nxt]<heap[cnt]) swap(heap[cnt],heap[nxt]); // 反正左右都行时 随意换
        else break;
        cnt=nxt;
    }
    return ;
}

int top(){
    return heap[1];
}

int n,m,cmd,x;
int main() {
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>cmd;
        if(cmd==1){
            cin>>x;
            push(x);
        }else if(cmd==2){
            cout<<top()<<endl;
        }else if(cmd==3){
            pop();
        }
    }
    return 0;
}

超市
贪心 优先队列模拟 放前d天的 不能就尽可能放val大的

#include <bits/stdc++.h>
using namespace std;

const int maxn = 4e6+5;
priority_queue<int,vector<int>,greater<int> > que;

struct node{
	int val;
	int d; 
	bool operator < (const node & a)const{
		return d<a.d;
	} 
}a[maxn];

signed main() {
	int n;
	while(cin>>n){
		int day;
		for(int i=1;i<=n;i++){
			cin>>a[i].val>>a[i].d;
		}
		sort(a+1,a+1+n);
		for(int i=1;i<=n;i++){
			day=a[i].d;
			if(que.size()<day) que.push(a[i].val);
			else{
				if(que.top()<a[i].val){
					que.pop();
					que.push(a[i].val);
				}
			}
		}
		int ans=0;
		while(!que.empty()){
			ans+=que.top();
			que.pop();
		}
		cout<<ans<<endl;
	}
	return 0;
}

Sequence
提前放进去第一层 然后每取一个 把它之后的再放入 就不MLE了

#include <bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
const int maxe=2e5+10;
int n,m,cnt;

int a[maxn],b[maxn];

struct node{
    int sum,p1,p2;
    bool operator < (node const & a)const {
        return a.sum<sum;
    }
};

priority_queue<node> que; 

int main() {
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=n;i++) {
        cin>>b[i];
        que.push(node{a[1]+b[i],1,i});
    }
    for(int i=1;i<=n;i++){
        node p=que.top();
        cout<<p.sum<<" ";
        que.pop();
        que.push(node{a[p.p1+1]+b[p.p2],p.p1+1,p.p2});
    }
    
    return 0;
}

数据备份
模拟链表 + 贪心
当选择了num[i]后,反悔了,反之选择选了num[i-1]和num[i+1]时,获利便增加了num[i-1]+num[i+1]-num[i]。所以当num[i]被选时,我们就可以删去num[i-1]和num[i+1],即为其代表的vis数组打上标记并把num[i]改成num[i-1]+num[i+1]-num[i],放进堆中,重新找最大的。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 4e6+5;

struct node {
	int id,val;
	bool operator < (const node & a)const {
		return val>a.val;
	}
};
priority_queue<node> que;
int a[maxn];

bool vis[maxn];
int l[maxn],r[maxn];
signed main() {
	int n,k;
	cin>>n>>k;
	for(int i = 0; i < n; i ++ ) cin >> a[i];
	for(int i = n - 1; i>=1; i -- ) a[i] -= a[i - 1];
	for(int i=1; i<n; i++) l[i]=i-1,r[i]=i+1,que.push(node {i,a[i]});
	l[0]=0,r[n-1]=n;
	a[0]=a[n]=0x3f3f3f3f;
	int ans=0;
	for(int i=1; i<=k; i++) {
		while(!que.empty()&&vis[que.top().id]) que.pop();
		node t=que.top();
		que.pop();
		ans+=t.val;
		
		vis[r[t.id]]=vis[l[t.id]]=1;
		a[t.id]=a[l[t.id]]+a[r[t.id]]-a[t.id];

		l[t.id]=l[l[t.id]];
		r[t.id]=r[r[t.id]];

		l[r[t.id]]=t.id;
		r[l[t.id]]=t.id;

		que.push(node {t.id,a[t.id]});
	}
	cout<<ans<<endl;
	return 0;
}

Huffman树 贪心
荷马史诗

每次都是将k个节点合并为1个(减少k-1个),一共要将n个节点合并为1个,如果(n-1)%(k-1)!=0 则最后一次合并时不足k个。也就表明了最靠近根节点的位置反而没有被排满,因此我们需要加入k-1-(n-1)%(k-1)个空节点使每次合并都够k个节点(也就是利用空节点将其余的节点挤到更优的位置上)。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 100000 + 5 ;
const int INF = 0x3f3f3f3f ;

struct node {
    int w,h;
    bool operator < (node const & a) const {
        return a.w<w||(a.w==w&&a.h<h);
    }
};

priority_queue<node> que;

signed main() {
    int n,k,m;
    cin>>n>>k;
    int cnt=0;
    if((n-1)%(k-1)) cnt+=(k-1)-(n-1)%(k-1);
    for(int i=1; i<=cnt; i++) que.push(node {0,0});
    cnt+=n;
    for(int i=1; i<=n; i++) {
        cin>>m;
        que.push(node {m,0});
    }
    int ans=0;
    while(que.size()>1) {
        int res=0,hh=-1;
        for(int i=0; i<k; i++) {
            hh=max(que.top().h,hh);
            res+=que.top().w;
            que.pop();
        }
        ans+=res;
        que.push(node {res,hh+1});
    }
    cout<<ans<<endl<<que.top().h<<endl;
    return 0;
}