noip 2018 模擬賽9
阿新 • • 發佈:2018-12-17
——policy(3115)
Description:
有一個的矩形,現在有次詢問,每次詢問一個的子矩形,若它的最大值mx,權值和為sum,求。
Solution:
- 發現這個就是一個無腦的資料結構題
- 複雜度實在太卡…那麼帶的話很容易就掛
- 所以就想到一些線性的做法,比如單調佇列
- 這樣複雜度就是
Code:
#include<bits/stdc++.h> using namespace std; #define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i) #define SREP(i,f,t) for(int i=(f),i##_end_=(t);i<i##_end_;++i) #define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;--i) #define ll long long template<class T>inline bool chkmin(T &x,T y){return x>y?x=y,1:0;} template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;} template<class T>inline void Rd(T &x){ x=0;char c; while((c=getchar())<48); do x=(x<<1)+(x<<3)+(c^48); while((c=getchar())>47); } const int N=1002; #define INF 0x3f3f3f3f3f3f3f3fll int n,m,q; int a,b; int A[N][N],B[N][N],Q[N]; ll sum[N][N]; void solve(){ ll ans=INF; REP(i,1,n){ int l=0,r=0; REP(j,1,m){ while(l<r && Q[l]<=j-b) ++l; while(l<r && A[i][Q[r-1]]<A[i][j]) --r; Q[r++]=j; B[i][j]=A[i][Q[l]]; } } REP(j,b,m){ int l=0,r=0; REP(i,1,n){ while(l<r && Q[l]<=i-a) ++l; while(l<r && B[Q[r-1]][j]<B[i][j]) --r; Q[r++]=i; if(a<=i){ ll x=sum[i][j]-sum[i-a][j]-sum[i][j-b]+sum[i-a][j-b]; ll y=1ll*B[Q[l]][j]*a*b; chkmin(ans,y-x); } } } printf("%lld\n",ans); } int main(){ // freopen("policy.in","r",stdin); // freopen("policy.out","w",stdout); Rd(n),Rd(m); REP(i,1,n) REP(j,1,m)Rd(A[i][j]),sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+A[i][j]; Rd(q); while(q--)Rd(a),Rd(b),solve(); return 0; }
——ricehub(3074)
Description: 在一條軸上,有個米倉,每個米倉的的糧食都是,且知道它們的位置,以及座標範圍。問在某個點建一個倉庫,在總花費不超過的情況下,求最大的倉庫糧食量,一糧食每一單位的運費為。
Solution:
- 首先有一個的做法
- 因為倉庫只對一個區間的米倉有影響
- 模擬資料發現,它對花費的最優貢獻一定是
- 即倉庫要建在中位數時最優。
- 那麼對於每個左端點,我們可以線性找到它的右端點,再利用字首和求一個最優花費是否超過即可。
Code:
#include<bits/stdc++.h>
using namespace std;
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;++i)
#define SREP(i,f,t) for(int i=(f),i##_end_=(t);i<i##_end_;++i)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;--i)
#define ll long long
template<class T>inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
template<class T>inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
template<class T>inline void Rd(T &x){
x=0;char c;
while((c=getchar())<48);
do x=(x<<1)+(x<<3)+(c^48);
while((c=getchar())>47);
}
const int N=1e5+2;
int n,L;
ll B;
int p[N];
struct p20{
void solve(){
int ans=0;
REP(i,1,n) REP(j,i+1,n) {
int l=i,r=j;
ll sum=0;
while(l<r) sum+=p[r]-p[l],l++,r--;
if(sum<=B) chkmax(ans,j-i+1);
}
printf("%d\n",ans);
}
}p1;
struct p100{
ll sum[N];
bool check(int l,int r){
int mid=(l+r)>>1;
ll cost=1ll*p[mid]*(mid-l+1)-(sum[mid]-sum[l-1])+sum[r]-sum[mid]-1ll*p[mid]*(r-mid);
return cost<=B;
}
void solve(){
REP(i,1,n) sum[i]=sum[i-1]+p[i];
int j=1,ans=0;
REP(i,1,n){
while(j<=n && check(i,j)) ++j;
chkmax(ans,j-i);
}
printf("%d\n",ans);
}
}p2;
int main(){
// freopen("ricehub.in","r",stdin);
// freopen("ricehub.out","w",stdout);
Rd(n),Rd(L),Rd(B);
REP(i,1,n) Rd(p[i]);
// if(n<=100)p1.solve();//O(n^3)
// else
p2.solve();
return 0;
}
——war(3117)
Description:
有一個個點,條邊的圖,每個點都有顏色,顏色種類的範圍為。 現在有個操作,每個操作將點的顏色改為,在每個操作後求不同顏色的最小距離。
Solution:
- 待更新
Code