我是一个小沙比,爆零本领强~
T1
看起来是一道很捞的、做过无数遍的区间最大值。
直接$O(n^3)$做一做就完了……
具体做法就是预处理每行的前缀和,然后二重循环枚举一个固定的列区间,再用单调队列的思想,从第一行不停向下扩展行区间,如果矩阵内总和$\gt k$ 了就从行区间顶部不停删行,删到矩阵内总和$\le k$ 为止。每当矩阵总和满足限制时,更新矩阵面积最大值即可。
当然如果你很想大战$T1$的话,可以写个$O(n^2*log(n^2))$的主席树?
1 #include<cmath> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define N 501 8 using namespace std; 9 inline int read(){ 10 int x=0; bool f=1; char c=getchar(); 11 for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=0; 12 for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^‘0‘); 13 if(f) return x; 14 return 0-x; 15 } 16 int n,m,e[N][N],sum[N][N],x,ans; 17 int main(){ 18 n=read()+1,m=read(); 19 int i,j,k,go; 20 for(i=1;i^n;++i) 21 for(j=1;j^n;++j) 22 sum[i][j]=sum[i][j-1]+read(); 23 for(i=1;i^n;++i){ 24 for(j=i;j^n;++j){ 25 x=0, go=1; 26 for(k=1;k^n;++k){ 27 x+=sum[k][j]-sum[k][i-1]; 28 while(x>m) x-=sum[go][j]-sum[go][i-1], ++go; 29 ans=max(ans,(j-i+1)*(k-go+1)); 30 } 31 } 32 } 33 printf("%d\n",ans); 34 return 0; 35 }
T2
这是一道考验水平的$dp$题(机房最高分$70$)
0~30pts:
你写的开心就好
40~50pts:
不知道
60~90pts:
由于是一条链,所以可以考虑链上$dp$,从前往后推。
设$f(i)$为从根到$i$号节点中,让每个点都得到补给所需的总代价的最小值。
易推$f(i)=$\min\{f(j-1)+$
100pts:
这个dp有点新式……
设$f(i,j)$为以$i$号节点为根的子树中,离点$i$最近的机场设在了节点$j$时,子树中所有点都得到补给所需的总代价的最小值。
然后转移是这样的
T3
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define N 152505 4 const ll inf=1ll<<62; 5 using namespace std; 6 inline int read(){ 7 int x=0; bool f=1; char c=getchar(); 8 for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=0; 9 for(; isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+(c^‘0‘); 10 if(f) return x; 11 return 0-x; 12 } 13 int n,s,t,x[N],y[N],z[N],l[N],r[N]; 14 int root,L,R,u; ll Dis; 15 struct SegTree{ 16 struct T{ 17 int son[2]; 18 ll dis,tag; //min,max 19 bool del; 20 }tr[N<<3]; 21 int cnt; 22 inline void pushup(int o){ 23 tr[o].dis = min(tr[tr[o].son[0]].dis, tr[tr[o].son[1]].dis); 24 //printf("pushup:%lld %lld\n",tr[tr[o].son[0]].dis, tr[tr[o].son[1]].dis); 25 } 26 inline void pushdel(int o){ 27 tr[o].del = tr[tr[o].son[0]].del & tr[tr[o].son[1]].del; 28 } 29 void build(int &o,int l,int r){ 30 o=++cnt; 31 tr[o].tag=inf, tr[o].del=0; 32 if(l==r){tr[o].dis=inf; tr[o].son[0]=tr[o].son[1]=0; return;} 33 int mid=(l+r)>>1; 34 build(tr[o].son[0],l,mid), build(tr[o].son[1],mid+1,r); 35 pushup(o); 36 } 37 inline void pushdown(int o){ 38 if(tr[o].tag<inf){ 39 int lc=tr[o].son[0], rc=tr[o].son[1]; 40 if(!tr[lc].del) tr[lc].dis=min(tr[lc].dis,tr[o].tag), tr[lc].tag=min(tr[lc].tag,tr[o].tag); 41 if(!tr[rc].del) tr[rc].dis=min(tr[rc].dis,tr[o].tag), tr[rc].tag=min(tr[rc].tag,tr[o].tag); 42 tr[o].tag=inf; 43 } 44 } 45 void update(int o,int l,int r){ 46 if(tr[o].del) return; 47 if(L<=l && r<=R){ 48 tr[o].dis=min(tr[o].dis,Dis), tr[o].tag=min(tr[o].tag,Dis); 49 return; 50 } 51 pushdown(o); 52 int mid=(l+r)>>1; 53 if(L<=mid) update(tr[o].son[0],l,mid); 54 if(R>mid) update(tr[o].son[1],mid+1,r); 55 pushup(o); 56 } 57 void Delete(int o,int l,int r){ 58 if(l==r){tr[o].dis=inf; tr[o].del=1; return;} 59 pushdown(o); 60 int mid=(l+r)>>1; 61 if(u<=mid) Delete(tr[o].son[0],l,mid); 62 else Delete(tr[o].son[1],mid+1,r); 63 //printf("Delete:%d %d %lld\n",l,r,tr[o].dis); 64 pushup(o); //printf("Delete:%d %d %lld\n",l,r,tr[o].dis); 65 pushdel(o); 66 } 67 void query(int o,int l,int r){ //查询最小值的最小下标 68 //printf("query:%d %d %lld\n",l,r,tr[o].dis); 69 if(l==r){u=l, Dis=tr[o].dis; return;} 70 pushdown(o); 71 int mid=(l+r)>>1; 72 //printf("query:%d %d %lld %lld %lld\n",l,r,tr[o].dis,tr[tr[o].son[0]].dis,tr[tr[o].son[1]].dis); 73 if(tr[o].dis==tr[tr[o].son[0]].dis && !tr[tr[o].son[0]].del) query(tr[o].son[0],l,mid); 74 else if(tr[o].dis==tr[tr[o].son[1]].dis && !tr[tr[o].son[1]].del) query(tr[o].son[1],mid+1,r); 75 } 76 }S; 77 ll ans[N]; 78 void Dij(){ 79 L=R=s, Dis=0; 80 S.cnt=0; 81 S.update(root,1,n); 82 int i; 83 for(int i=1;i<=n;++i){ 84 S.query(root,1,n); 85 ans[u]=Dis; 86 //printf("%d %lld %d %d\n",u,ans[u],l[u],r[u]); 87 if(u==t) break; 88 Dis+=z[u]; 89 L=l[u],R=r[u]; 90 S.update(root,1,n); 91 S.Delete(root,1,n); 92 } 93 } 94 int main(){ 95 //freopen("trip9.in","r",stdin); 96 //freopen("trip.out","w",stdout); 97 n=read(),s=read(),t=read(); 98 int i; 99 for(i=1;i<=n;++i) x[i]=read(); 100 for(i=1;i<=n;++i) y[i]=read(); 101 for(i=1;i<=n;++i) z[i]=read(); 102 for(i=1;i<=n;++i){ 103 l[i]=lower_bound(x+1,x+n+1,x[i]-y[i])-x, 104 r[i]=upper_bound(x+1,x+n+1,x[i]+y[i])-x-1; 105 //cout<<i<<‘ ‘<<x[i]<<‘ ‘<<y[i]<<‘ ‘<<l[i]<<‘ ‘<<r[i]<<‘\n‘; 106 } 107 S.build(root,1,n); 108 Dij(); 109 printf("%lld\n",ans[t]); 110 return 0; 111 } 112 /* 113 7 3 7 114 -1 0 1 2 3 5 10 115 11 0 1 1 4 10 2 116 3 1 1 1 2 4 5 117 */
原文地址:https://www.cnblogs.com/scx2015noip-as-php/p/2018_10_22.html
时间: 2024-09-30 06:57:27