1.LOJ 507 接竹竿
dp[i]表示前i个的最大分数,所以dp[i]=max(dp[i-1],dp[j-1]+sum[i]-sum[j-1]) (color i ==color j&&i>j)选与不选的两种决策
但是这样跑为O(N^2),需要优化,发现dp[j-1]-sum[j-1]是个在之前知道的数,所以可以记录下来当需要用这种颜色时的最大dp[j-1]-sum[j-1]
用lst[i]表示在当前情况下需要用color i这种颜色时的最大dp[j-1]-sum[j-1]这个值,因为这两者之间的共处是颜色
所以用颜色维护
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; inline long long read() { long long f=1,ans=0;char c; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } long long n,k; long long c[6000001],v[6000001],lst[6000001],sum[6000001],dp[6000001]; int main() { memset(lst,-127/3,sizeof(lst)); n=read(),k=read(); for(long long i=1;i<=n;i++) c[i]=read(); for(long long i=1;i<=n;i++) v[i]=read(),sum[i]=sum[i-1]+v[i]; for(long long i=1;i<=n;i++) { dp[i]=max(dp[i-1],lst[c[i]]+sum[i]); lst[c[i]]=max(lst[c[i]],dp[i-1]-sum[i-1]); } cout<<dp[n]; }
2.LOJ 2279 降雨量
这道题先要仔细的读题,读完题后发现此题十分可做,但是最后全WA,因为没有看到它的含义是 X 年的降雨量不超过 Y 年这句话
分类讨论+ST表
先用ST表处理(i,j)之间的最大值(i,j为年份下标)
解决问题如果询问i,j
二分寻找u,v年份下标
用nx记录查找的下标对应的值是否等于此年份,因为有可能没有u,v年份的降雨量
然后分类讨论(this is 重点,not ST表)
1)nx==1时
1)ny==1时 已知 x,y(降水量) 那么首先判断x,y的大小,在判断包含区间的关系
2) ny==0时,说明只能与u进行比较,中间包含最大值与x的关系
2)nx==0
1) ny==1时,找中间包含区域与y的关系
2) ny==0,那么两头全部位置,所以maybe
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<cmath> using namespace std; inline long long read() { long long f=1,ans=0;char c; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } long long ma[50001]; long long n,m; long long maxn[50001][31]; long long query(long long l,long long r) { if(l>r) return -(2<<30-1); long long k=log2(r-l+1); return max(maxn[l][k],maxn[r-(1<<k)+1][k]); } long long num; int main() { // freopen("rainfall.in","r",stdin); // freopen("rainfall.out","w",stdout); // freopen("1.in","r",stdin); n=read(); for(long long i=1;i<=n;i++) { ma[i]=read(); maxn[i][0]=read(); } for(long long j=1;j<=log2(n);j++) for(long long i=1;i+(1<<j)-1<=n;i++) maxn[i][j]=max(maxn[i][j-1],maxn[i+(1<<(j-1))][j-1]); m=read(); for(long long i=1;i<=m;i++) { int ans; long long x=read(),y=read(); int sx=lower_bound(ma+1,ma+n+1,x)-ma,sy=lower_bound(ma+1,ma+n+1,y)-ma; bool nx=(sx<=n&&ma[sx]==x),ny=(sy<=n&&ma[sy]==y); // cout<<sx<<" "<<sy<<" "<<nx<<" "<<ny<<endl; if(nx) { if(ny) { int q=query(sx+1,sy-1); // cout<<q<<" "<<maxn[sx][0]<<" "<<maxn[sy][0]<<endl; if(maxn[sy][0]>maxn[sx][0]) ans=0; else if(q<maxn[sy][0]) { if(y-x+1==sy-sx+1) ans=1; else ans=-1; } else ans=0; } else{ int q=query(sx+1,sy-1); if(maxn[sx][0]>q) ans=-1; else ans=0; } } else{ if(ny) { int q=query(sx,sy-1); if(q<maxn[sy][0]) ans=-1; else ans=0; }else ans=-1; } if(ans==1) printf("true\n"); else if(ans==0) printf("false\n"); else printf("maybe\n"); } } /* 4 54 8606 77 7706 100 2149 123 900 1 2 54 */
3.LOJ 2332 焚风现象
因为是可以升降海拔高度的但是算的是差值,所以[u,v]区域内答案没有发生影响,至于(u-1,u)与(v,v+1)有影响
每次算值现将二者减去,再分别减,加差值,因为+w所以dis[u-1]+w ,但是对于v来说它是减数所以当他加上一个值时反而是减所以dis[v]-=w
dis[i]表示从i到i+1的海拔高
而因为若v=n时v+1已经越界所以就不再计算
此方法时间复杂度O(q+n)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; inline long long read() { long long f=1,ans=0;char c; while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();} while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();} return f*ans; } long long n,q,a[500001],s,t,dis[500001]; long long get(long long tt) { if(tt>0) return -s*tt; return -tt*t; } long long ans; int main() { n=read(),q=read(),s=read(),t=read(); for(long long i=0;i<=n;i++) a[i]=read(); for(long long i=0;i<n;i++) { dis[i]=a[i+1]-a[i]; ans+=get(dis[i]); } while(q--) { long long a=read(),b=read(),c=read(); ans-=get(dis[a-1]); dis[a-1]+=c; ans+=get(dis[a-1]); if(b!=n) { ans-=get(dis[b]); dis[b]-=c; ans+=get(dis[b]); } printf("%lld\n",ans); // cout<<ans<<endl; } }
总结:这其实是一场考试,最后100分收尾,只A了第三题,后来发现这是一场普及组的卷子,心态要炸