9.18 模拟赛
非常简单的一次模拟赛 但是由于水平太菜AK失败
T1 loj 507 接竹竿
题目大意:
一些纸牌 每个纸牌有花色分数 按顺序放入每个牌
放入每张牌之前 若牌中已有与这张牌花色相同的牌
可以选择将这张牌和任意一张花色相同的牌之间的所有牌全部取出,并得到与取出的所有牌点数和相同的分数
求最大得分
思路:
可以想到非常朴素的dp方程 dp i= max(dp i-1 , dp j-1 +sum j-i) (j与i同色)
设lst i 为i个颜色中 dp j-1 - sum j-1(第j张牌颜色为i)
维护这个数组即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 1001000 13 using namespace std; 14 inline ll read() 15 { 16 ll x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 ll n,k,s[MAXN],dp[MAXN],lst[MAXN],c[MAXN]; 22 int main() 23 { 24 n=read(),k=read(); 25 memset(lst,128,sizeof(lst)); 26 for(ll i=1;i<=n;i++) c[i]=read(); 27 for(ll i=1;i<=n;i++) s[i]=s[i-1]+read(); 28 for(ll i=1;i<=n;i++) 29 { 30 dp[i]=max(dp[i-1],s[i]+lst[c[i]]); 31 lst[c[i]]=max(lst[c[i]],dp[i-1]-s[i-1]); 32 } 33 printf("%lld",dp[n]); 34 }
因为没开long long所以爆炸了
T2 loj 降雨量
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 100100 13 using namespace std; 14 inline int read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 int n,m,hsh[MAXN],yr[MAXN],mx[MAXN<<2],val[MAXN]; 22 void mdf(int k,int l,int r,int x,int w) 23 { 24 if(l==r) {mx[k]=w;return ;} 25 int mid=(l+r)>>1; 26 if(x<=mid) mdf(k<<1,l,mid,x,w); 27 else mdf(k<<1|1,mid+1,r,x,w); 28 mx[k]=max(mx[k<<1],mx[k<<1|1]); 29 } 30 int query(int k,int l,int r,int a,int b) 31 { 32 if(a>b) return 0; 33 if(l==a&&r==b) return mx[k]; 34 int mid=(l+r)>>1; 35 if(b<=mid) return query(k<<1,l,mid,a,b); 36 else if(a>mid) return query(k<<1|1,mid+1,r,a,b); 37 else return max(query(k<<1,l,mid,a,mid),query(k<<1|1,mid+1,r,mid+1,b)); 38 } 39 int main() 40 { 41 n=read();int x,y,a,b,c; 42 for(int i=1;i<=n;i++) 43 {hsh[i]=read(),val[i]=read();mdf(1,1,n,i,val[i]);} 44 m=read(); 45 while(m--) 46 { 47 x=read(),y=read(); 48 if(x>=hsh[n]||y<=hsh[1]) {puts("maybe");continue;} 49 a=upper_bound(hsh+1,hsh+n+1,x)-hsh,b=lower_bound(hsh+1,hsh+n+1,y)-hsh; 50 c=query(1,1,n,a,b-1); 51 if(hsh[a-1]==x&&hsh[b]==y&&c<val[b]&&val[b]<=val[a-1]&&b-a+1==y-x) {puts("true");continue;} 52 if(hsh[b]==y&&c>=val[b]) {puts("false");continue;} 53 if(hsh[a-1]==x&&hsh[b]==y&&val[b]>val[a-1]) {puts("false");continue;} 54 if(hsh[a-1]==x&&c>=val[a-1]) {puts("false");continue;} 55 puts("maybe"); 56 } 57 }
这次的代码判断不那么naive了
但是由于没有判断线段树中查询区间左右端点的大小关系 有可能左边比右边大 所以爆炸了
T3 loj 2332 焚风现象
地表风的温度随海拔升降而变化。地点 0在海边,温度为 0度;对于任一地点 i(0⩽i<N),从地点i吹到地点 i+1的风的温差仅取决于两地的海拔差。具体来说:
- 如果 Ai=Ai+1 风的温度不变
- 如果 Ai<Ai+1 风每爬升1米,温度就会下降S度
- 如果 Ai>Ai+1 风每下沉1米,温度就会升高T度
IOI 国的地壳运动很强烈。你得到Q天来地壳运动的数据
第j日 (1⩽j⩽Q),地点 L-R 的海拔升高了 X(X可能为负数
每天运动后求地点N的温度
思路:
因为时间非常的短 所以有一个O n 的做法
维护一个类似于差分的数组 表示每一个地点与前一个地点的差
每次讨论一下区间造成的影响
根据差的正负和修改的正负 讨论即可
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #include<map> 10 #define inf 2139062143 11 #define ll long long 12 #define MAXN 200100 13 using namespace std; 14 inline ll read() 15 { 16 int x=0,f=1;char ch=getchar(); 17 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 18 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 19 return x*f; 20 } 21 ll n,m,S,T,a[MAXN],g[MAXN],ans; 22 int main() 23 { 24 n=read(),m=read(),S=read(),T=read();a[0]=read(); 25 for(int i=1;i<=n;i++) a[i]=read();int x,y,z; 26 for(int i=1;i<=n;i++) 27 { 28 g[i]=a[i]-a[i-1]; 29 if(g[i]>0) ans-=g[i]*S; 30 else ans-=g[i]*T; 31 } 32 while(m--) 33 { 34 x=read(),y=read(),z=read(); 35 if(z>0) 36 { 37 if(g[x]>0) ans-=z*S; 38 if(g[x]<=0&&g[x]+z<=0) ans-=z*T; 39 if(g[x]<=0&&g[x]+z>0) ans+=g[x]*T-(z+g[x])*S; 40 //cout<<g[x]<<" "<<g[y+1]<<endl; 41 g[x]+=z; 42 if(y==n) goto ed; 43 if(g[y+1]<0) ans+=z*T; 44 if(g[y+1]>=0&&g[y+1]-z>=0) ans+=z*S; 45 if(g[y+1]>=0&&g[y+1]-z<0) ans+=g[y+1]*S-(g[y+1]-z)*T; 46 g[y+1]-=z; 47 } 48 if(z<0) 49 { 50 if(g[x]<0) ans-=z*T; 51 if(g[x]>=0&&g[x]+z>=0) ans-=z*S; 52 if(g[x]>=0&&g[x]+z<0) ans+=g[x]*S-(z+g[x])*T; 53 g[x]+=z; 54 if(y==n) goto ed; 55 if(g[y+1]>0) ans+=z*S; 56 if(g[y+1]<=0&&g[y+1]-z<=0) ans+=z*T; 57 if(g[y+1]<=0&&g[y+1]-z>0) ans+=g[y+1]*T-(g[y+1]-z)*S; 58 g[y+1]-=z; 59 } 60 ed: printf("%lld\n",ans); 61 } 62 }
再次因为没long long 爆炸