给定n个数字b_j,r个数字a_i
1.判断下面方程是否有整数解
1+∑i=1rxi∗ai=bj
2.r++,增加a_r,r最多为20
#include <cstdio>
#include <queue>
using namespace std;
typedef long long ll;
const int N=1e5+5,K=1e4+5;
ll h;
int n,m,k;
ll a[N];
int c[N];
int len;
ll d[K];
bool inq[K];
int head,tail,q[K];
typedef pair<int,int> pr;
priority_queue<pr> s;
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
#endif // Dou
scanf("%I64d%d%d%d",&h,&n,&m,&k);
d[0]=0;
for(int u=1;u<k;u++) d[u]=h;
for(int i=1;i<=n;i++){
scanf("%I64d%d",&a[i],&c[i]);
if((--a[i])%k==0) s.push(pr(c[i],-i));
}
while(m--){
int type; scanf("%d",&type);
if(type==1){
ll w; scanf("%I64d",&w);
head=tail=0;
for(int u=0;u<k;u++) if(d[u]!=h) q[tail++]=u,inq[u]=1;
while(head!=tail){
int u=q[head]; ++head==K?head=0:0; inq[u]=0;
ll t=d[u]+w;
int v=t%k;
if(t<d[v]){
d[v]=t;
if(!inq[v]) q[tail]=v,++tail==K?tail=0:0,inq[v]=1;
}
}
while(!s.empty()) s.pop();
for(int i=1;i<=n;i++) if(a[i]>=d[a[i]%k]&&c[i])
s.push(pr(c[i],-i));
}
else if(type==2){
int x,y; scanf("%d%d",&x,&y);
c[x]-=y;
if(a[x]>=d[a[x]%k])
s.push(pr(c[x],-x));
}
else{
while(!s.empty()&&c[-s.top().second]!=s.top().first) s.pop();
if(s.empty()){
puts("0");
continue;
}
printf("%d\n",s.top().first);
c[-s.top().second]=0;
s.pop();
}
}
}