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 }
View Code

因为没开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 }
View Code

这次的代码判断不那么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 }
View Code

 再次因为没long long 爆炸

posted @ 2018-09-18 19:00  jack_yyc  阅读(181)  评论(0编辑  收藏  举报