Codeforces Round #546 (Div. 2)

A. Nastya Is Reading a Book

题意:书分为n个章节  给出连续的章节页码 给出当前页数 问有多少章没有看完 

思路 :直接模拟即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=100+5;
 4 int l[maxn],r[maxn];
 5 int main(){
 6 int n;
 7 scanf("%d",&n);
 8 for(int i=0;i<n;i++)scanf("%d%d",&l[i],&r[i]);
 9 int ans=0;
10 int p;
11 scanf("%d",&p);
12 for(int i=0;i<n;i++){
13     if(p>=l[i]&&p<=r[i]){
14         
15         {cout<<n-i;return 0;}
16     }
17 }
18 cout<<0<<endl;
19 return 0;
20 }
View Code

B. Nastya Is Playing Computer Games

题意:有n个井盖 每个井盖上面都有一块石头 怪力girl 可以执行 以下操作:把一块石头扔到任意一个井盖上   移动一步  问最小几个操作达成全部井盖都被翻开过的成就

思路:肯定要重复走一段路 直接选择短的那段路重复走即可  并且N>=2 必有  扔3次石头的操作  然后就每次把石头扔到一起即可

1 #include<bits/stdc++.h>
2 using namespace std;
3 const int maxn=100+5;
4 int main(){
5 int n,k;
6 scanf("%d%d",&n,&k);
7 printf("%d\n",min(n-k,k-1)+3*(n-2)+6);
8 return 0;
9 }
View Code

C. Nastya Is Transposing Matrices

题意 给出两个矩阵A B 可以随便选择A的子矩阵转置  可以操作任意次  问A有没有可能变成B

思路:每次转置 斜线上(从左下到右上的线)的元素都是不变的 直接比较斜线上的元素即可

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=500+5;
 4 int a[maxn][maxn],b[maxn][maxn];
 5 multiset<int>x[maxn*10],y[maxn*10];
 6 int main(){
 7     int n,m;
 8     scanf("%d%d",&n,&m);
 9     
10     for(int i=0;i<n;i++){
11         for(int j=0;j<m;j++)scanf("%d",&a[i][j]);
12     }
13     
14     for(int i=0;i<n;i++){
15         for(int j=0;j<m;j++)scanf("%d",&b[i][j]);
16     }
17     for(int i=0;i<n;i++){
18         for(int j=0;j<m;j++){
19             x[i+j].insert(a[i][j]);
20             y[i+j].insert(b[i][j]);
21         }
22     }
23     int flag=1;
24     for(int i=0;i<=n+m;i++){
25         if(x[i]!=y[i]){flag=0;break;}
26     }
27     if(flag)printf("YES\n");
28     else printf("NO\n");
29 
30     return 0;
31 }
View Code

D. Nastya Is Buying Lunch

题意:有n个人在排队 给出m个单向边  满足单向边的(要求相邻)即可换位置  问 从队伍的最后一名最多能前进多少个位置

思路:这题的方法很巧妙   以整体处理局部,表示局部状态的思想  类似于 不同数字   的序列  a1 a2 a3 ...an 只要max-min+1==n 那么这个序列就是1--n没有重复数字的序列

而本题 使用cnt[p]  表示p后面有多少个可以和p换位置的   如果 cnt[p]==n-i-ans(ans表示递推到当前位置时,有多少个可以换位置的) 那么P就可以换位置  ans++即可 如果p不能换位置 

那么就把与p相连的在p前面的cnt++ (这里循环里面是把前后都更新了,因为更新排在后面的没有影响,所以为了减少代码量可以直接也更新)也就是前面的可以和p换位置的cnt要更新 

最后即可得到最后答案

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=3e5+5;
 4 int p[maxn];
 5 int cnt[maxn];
 6 vector<int>q[maxn];
 7 int main(){
 8 int n,m;
 9 scanf("%d%d",&n,&m);
10 int tmp;
11 for(int i=1;i<=n;i++){
12     scanf("%d",&p[i]);
13 }  
14 
15 int x,y;
16 for(int i=0;i<m;i++){
17     scanf("%d%d",&x,&y);
18     q[y].push_back(x);
19 }
20 for(int i=0;i<q[p[n]].size();i++){
21     cnt[q[p[n]][i]]++;
22 }
23 int ans=0;
24 for(int i=n-1;i>=1;i--){
25     if(n-i-ans==cnt[p[i]])ans++;
26     else {
27         for(int j=0;j<q[p[i]].size();j++){
28             cnt[q[p[i]][j]]++;
29         }
30     }
31 }
32 cout<<ans<<endl;
33 return 0;
34 }
View Code

E. Nastya Hasn't Written a Legend

题意:给出一个n个元素的序列a   n-1个元素的序列k  有以下操作:1.将a[i]+x 若a[i]+k[i]> a[i+1]  a[i+1]就变成a[i]+k[i] 并且拿新的a[i+1]+k[i+1]和a[i+2]进行对比重复上述操作

                               2.计算 l 到r的和

思路:明显是一道线段树的题目 关键在于如何转换条件到可以用线段树维护 (第一次做这种类型的题目,所以直接上了题解)

贴上了cf的题解:https://codeforces.com/blog/entry/65905  

我在此 做一个翻译机

将a 序列转换成b序列  如果b[i]加上x后 b[i]>b[i+1]那么b[i+1]=b[i]以此类推 ,这样就把不确定不相等的值k给隐藏掉了 妙啊   那么只要找到第一个位置  b[pos]>=b[i]+x  pos之前到加的第一个元素都会变成

b[i]+x  这样就可以很方便地用线段树维护鸟    这里找位置使用二分  用线段树维护一个最大值   即可二分 因为求的是b 序列   b=a[i]-t[i] 所以 sigma(b[l,r])=sigma[a[l,r]]-sigma(t[l,r])=>  sigma(a[l,r])=sigma(b[l,r]+t[l,r]) t用前缀和即可O(1)用b 算出a 

  1 #include<bits/stdc++.h>
  2 #define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;i++)
  3 #define MS(arr,arr_value) memset(arr,arr_value,sizeof(arr)) 
  4 #define F first 
  5 #define S second
  6 #define pii pair<int ,int >
  7 #define mkp make_pair
  8 #define pb push_back
  9 using namespace std;
 10 typedef long long ll;
 11 const int inf =0x3f3f3f3f;
 12 const int maxn=1e5+5;
 13 ll laz1[maxn<<2],laz2[maxn<<2],sum[maxn<<2],maxnum[maxn<<2],sum1[maxn],sum2[maxn];
 14 ll a[maxn],k[maxn];
 15 int n,q;
 16 void mdf(int o,int l,int r,ll v){
 17     sum[o]=(r-l+1)*v;
 18     laz1[o]=v;
 19     maxnum[o]=v;
 20 }
 21 void push_up(int o){
 22     sum[o]=sum[o<<1|1]+sum[o<<1];
 23     maxnum[o]=max(maxnum[o<<1],maxnum[o<<1|1]);
 24 }
 25 void build(int o,int l,int r){
 26     laz1[o]=-inf;
 27     if(l==r){
 28         maxnum[o]=sum[o]=a[l];    
 29         return ;
 30     }
 31     int mid=l+r>>1;
 32     build(o<<1,l,mid);
 33     build(o<<1|1,mid+1,r);
 34     push_up(o);
 35 }
 36 void push_down(int o,int l,int r){
 37     if(laz1[o]!=-inf){
 38         int mid=l+r>>1;
 39         mdf(o<<1,l,mid,laz1[o]);
 40         mdf(o<<1|1,mid+1,r,laz1[o]);
 41         laz1[o]=-inf;
 42     }
 43 }
 44 void update(int o,int l,int r,int x,int y,ll v){
 45     if(x>y)return ;
 46     if(l>=x&&y>=r){
 47         mdf(o,l,r,v);
 48         return ;
 49     }
 50     int mid=l+r>>1;
 51     push_down(o,l,r);
 52     if(mid>=x)update(o<<1,l,mid,x,y,v);
 53     if(mid+1<=y)update(o<<1|1,mid+1,r,x,y,v);
 54     push_up(o);
 55 }
 56 ll query(int o,int l,int r,int x,int y){
 57     if(x>y)return 0;
 58     if(x<=l&&r<=y){
 59         return sum[o];
 60     }
 61     int mid=l+r>>1;
 62     ll ans=0;
 63     push_down(o,l,r);
 64     if(mid>=x)ans+=query(o<<1,l,mid,x,y);
 65     if(mid+1<=y)ans+=query(o<<1|1,mid+1,r,x,y);
 66     return ans;
 67 }
 68 ll querymax(int o,int l,int r,int x,int y){
 69     if(x>y)return -inf;
 70     if(l>=x&&r<=y)return maxnum[o];
 71     int mid=l+r>>1;
 72     push_down(o,l,r);
 73       if (mid < x)
 74         return querymax(o << 1 | 1,mid + 1,r,x,y);
 75     if (mid + 1 > y)
 76         return querymax(o << 1,l,mid,x,y);
 77     return max(querymax(o << 1,l,mid,x,y),querymax(o << 1 | 1,mid + 1,r,x,y));
 78 
 79 }
 80 char s[20];
 81 int u,v;
 82 int main(){
 83     scanf("%d",&n);
 84     FOR(i,1,n)scanf("%lld",&a[i]);
 85     FOR(i,1,n-1)scanf("%lld",&k[i]);
 86     for(int i=1;i<=n-1;i++){
 87         sum1[i]=sum1[i-1]+k[i];
 88         a[i+1]-=sum1[i];
 89         sum2[i]=sum1[i]+sum2[i-1];
 90     }
 91     build(1,1,n);
 92     scanf("%d",&q);
 93     while(q--){
 94         scanf("%s",&s);
 95             scanf("%d%d",&u,&v);
 96         if(s[0]=='+'){
 97             int left=u,right=n,ans=-1;
 98             ll tmp=querymax(1,1,n,u,u);
 99 
100                 while(left<right){
101                     int mid=left+right+1>>1;
102                     if(querymax(1,1,n,u+1,mid)>=tmp+v){
103                         right=mid-1;
104             }
105                     else left=mid;
106                 }
107                 update(1,1,n,u,left,tmp+v);
108 
109         }
110         else {
111             printf("%lld\n",query(1,1,n,u,v)+sum2[v-1]-sum2[max(0,u-2)]);
112         }
113     
114     }
115 }
View Code

 

转载于:https://www.cnblogs.com/ttttttttrx/p/10604624.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值