分塊大法好!node
每個塊內維護單調上升序列c++
而後塊之間暴力lower_boundapp
複雜度$n*\sqrt n log(\sqrt n)$dom
#include<bits/stdc++.h> using namespace std; #define ll int #define A 100005 ll t,n,m,t2; ll bl[A],h[A],mx[410],sz[410]; ll st[410][410];//可是複雜度不對啊! int main(){ freopen("TaoPApp.in","r",stdin); freopen("TaoPApp.out","w",stdout); scanf("%d%d",&n,&m); t=sqrt(n); for(ll i=1;i<=n;i++){ scanf("%d",&h[i]); bl[i]=(i-1)/t+1; t2=max(t2,bl[i]); } for(ll i=1;i<=n;i++){ ll belong=bl[i]; mx[belong]=max(mx[belong],h[i]); if(!sz[belong]){ sz[belong]++; st[belong][sz[belong]]=h[i]; continue ; } else if(h[i]>st[belong][sz[belong]]){ sz[belong]++; st[belong][sz[belong]]=h[i]; } } for(ll i=1;i<=m;i++){ ll pla,hnow,lst; scanf("%d%d",&pla,&hnow); ll belong=bl[pla],maxnow=0,cnt=0; lst=h[pla];h[pla]=hnow; for(ll j=1;j<=t2;j++){ if(j==belong){ for(ll k=(j-1)*t+1;k<=min(j*t,n);k++){ if(h[k]>maxnow){ maxnow=h[k]; cnt++; } } } else { if(mx[j]>maxnow){ cnt+=(sz[j]-(upper_bound(st[j]+1,st[j]+sz[j]+1,maxnow)-st[j])+1); maxnow=mx[j]; } } } h[pla]=lst; printf("%d\n",cnt); } }
或者能夠線段樹ide
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 5555555 struct node{ ll l,r,max,val; }tr[A]; ll a[A]; ll n,m,lst; void built(ll x,ll l,ll r){ tr[x].l=l,tr[x].r=r; if(l==r){ return ; } ll mid=(l+r)>>1; built(x<<1,l,mid); built(x<<1|1,mid+1,r); } ll ask(ll x,ll val){ if(tr[x].l==tr[x].r) return tr[x].max>val; ll mid=(tr[x].l+tr[x].r)>>1; if(tr[x<<1].max<=val) return ask(x<<1|1,val); else return ask(x<<1,val)+tr[x].val-tr[x<<1].val; } void up(ll x){ tr[x].max=max(tr[x<<1].max,tr[x<<1|1].max); tr[x].val=tr[x<<1].val+ask(x<<1|1,tr[x<<1].max); } void change(ll x,ll pla,ll val){ if(tr[x].l==tr[x].r){ tr[x].val=1; tr[x].max=a[pla]; return ; } ll mid=(tr[x].l+tr[x].r)>>1; if(mid>=pla) change(x<<1,pla,val); else change(x<<1|1,pla,val); up(x); } int main(){ freopen("TaoPApp.in","r",stdin); freopen("TaoPApp.out","w",stdout); scanf("%lld%lld",&n,&m); built(1,1,n); for(ll i=1;i<=n;i++){ scanf("%lld",&a[i]); change(1,i,a[i]); } for(ll i=1;i<=m;i++){ ll p,h; scanf("%lld%lld",&p,&h); lst=a[p]; a[p]=h; change(1,p,a[p]); printf("%lld\n",tr[1].val); a[p]=lst; change(1,p,a[p]); } }
然而分塊比線段樹快的多ui
dp不可作就要往貪心\二分上想了spa
貪心考慮每原材料code
val[1]=s1[1].c; for(ll i=2;i<=k;i++){ val[i]=min(val[i-1]+s2[i-1].R,s1[i].c); }
咱們先把全部電腦生產出來,等賣出時再計算生產消耗,能生產就生產blog
貪心賣就是賣出生產代價最小的it
證實:若是最後生產代價大生產代價小都賣出去了,那麼和先賣生產代價小再賣生產代價大,狀況同樣
若是生產代價小沒賣出去,而賣出生產代價大的確定不優
因而拿個堆維護一下
這種費用滯後計算思想仍是要見一見
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 111111 ll read(){ ll x;scanf("%lld",&x);return x; } ll tot,n,k,tot2,ans; ll val[A]; struct node{ ll val,sum; node(){} node(const ll &a,const ll &b){val=a;sum=b;} friend bool operator < (const node &a,const node &b){ return a.val<b.val; } }tmp[A],now[A]; struct some{ ll c;//原材料價格 ll d;//至少d個電腦 ll m;//生產電腦費用 ll p;//能夠生產p臺 ll e;//最多儲存e臺 ll R;//儲存消耗R ll E;//儲存電腦消耗 }s1[A],s2[A]; int main(){ freopen("happy.in","r",stdin); freopen("happy.out","w",stdout); scanf("%lld",&k); for(ll i=1;i<=k;i++){ scanf("%lld%lld%lld%lld",&s1[i].c,&s1[i].d,&s1[i].m,&s1[i].p); } for(ll i=1;i<=k-1;i++){ scanf("%lld%lld%lld",&s2[i].e,&s2[i].R,&s2[i].E); } val[1]=s1[1].c; for(ll i=2;i<=k;i++){ val[i]=min(val[i-1]+s2[i-1].R,s1[i].c); } for(ll i=1;i<=k;i++){ for(ll j=1;j<=tot;j++) tmp[j].val+=s2[i-1].E; tmp[++tot]=node(val[i]+s1[i].m,s1[i].p); // printf("s1.d=%lld\n",s1[i].d); sort(tmp+1,tmp+tot+1); ll ned=s1[i].d,cun=s2[i].e; for(ll j=1;j<=tot;j++){ if(tmp[j].sum<=ned){ ans+=tmp[j].sum*tmp[j].val; // printf("i=%lld val=%lld sum=%lld\n",i,tmp[j].val,tmp[j].sum); ned-=tmp[j].sum; tmp[j].sum=0; } else { ans+=ned*tmp[j].val; // printf("val=%lld ned=%lld\n",tmp[j].val,ned); tmp[j].sum-=ned; ned=0; } } if(ned){ puts("-1"); return 0; } // printf("ans=%lld\n",ans); tot2=0; for(ll j=1;j<=tot;j++){ if(tmp[j].sum==0) continue ; if(tmp[j].sum<=cun){ now[++tot2]=tmp[j]; cun-=tmp[j].sum; } else { now[++tot2]=node(tmp[j].val,cun); cun=0; } } tot=tot2; for(ll j=1;j<=tot;j++) tmp[j]=now[j]; } printf("%lld\n",ans); }
發現check是O1的(維護前綴和)然而可能初始給定序列根本組不成
而後能夠每random_shuffle1次再check500000次
進行上述操做50次就AC了
#include<bits/stdc++.h> using namespace std; #define ll long long #define A 1111111 struct node{ ll a,b,id; }c[A]; ll suma[A],sumb[A],sa,sb,n; ll random(ll x){ return rand()%x; } int main(){ freopen("grandmaster.in","r",stdin); freopen("grandmaster.out","w",stdout); srand((unsigned)time(0)); scanf("%lld",&n); for(ll i=1;i<=2*n+1;i++){ scanf("%lld%lld",&c[i].a,&c[i].b); c[i].id=i; sa+=c[i].a,sb+=c[i].b; } for(ll i=1;i*n<=1000000;i++){ random_shuffle(c+1,c+2*n+2); for(ll j=1;j<=2*n+1;j++) suma[j]=suma[j-1]+c[j].a, sumb[j]=sumb[j-1]+c[j].b; for(ll j=1;j<=n;j++){ ll l=random(n+1)+1; if(suma[l+n]-suma[l-1]>sa-(suma[l+n]-suma[l-1])) if(sumb[l+n]-sumb[l-1]>sb-(sumb[l+n]-sumb[l-1])){ for(ll k=l;k<=l+n;k++) printf("%lld\n",c[k].id); return 0; } } if(clock()>990000){ printf("-1\n"); return 0; } } }