CF #546 (Div. 2) A(模拟) B(贪心)C(规律)D(思维+规律)E(二分+线段树)

Contest:http://codeforces.com/contest/1136

第一次把一个Div2写完了,还是有点小激动的,虽然这场似乎不是很难。

A. Nastya Is Reading a Book(模拟)

题目链接:http://codeforces.com/contest/1136/problem/A

题目大意:读一本书,分n个章节。给你一个页码数,问还剩多少张没有读完(页码数在本章末尾代表这章没有读完)。

思路:模拟即可。

ACCode:

const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll mod=192600817;
const double EPS=1.0e-8;
const double PI=acos(-1.0);

int ans[MAXN];

int main(){
	int n;
	while(~scanf("%d",&n)){
		int a,b;
		for(int i=1;i<=n;++i){
			scanf("%d%d",&a,&b);
			ans[i]=b;
		}int res=0,k;scanf("%d",&k);
		for(int i=1;i<=n;++i){
			if(ans[i]>=k){
				break;
			}++res;
		}printf("%d\n",n-res);
	}
	
}

B. Nastya Is Playing Computer Games(贪心)

题目链接:http://codeforces.com/contest/1136/problem/B

题目大意:给出n个井盖,每个井盖上面有一个石头。每个井盖下面有一个硬币。一个人一开始在第k个井盖上面,问最少需要多少步能够拿到所有的硬币。一步可以用来:1.将一块石头搬到相邻的井盖上 2.移动到相邻的井盖 3. 掀开井盖拿出硬币并合上井盖。

思路:很明显,发现先一直向井盖少的方向移动,然后再向另一端移动。贪心。

ACCode:

const int MAXN=1e5+10;

int n,k;

int main(){
	while(~scanf("%d%d",&n,&k)){
		int l=k-1,r=n-k;
		int ans=2;
		if(l<r){//fitst to left
			ans+=3*l;//go to the laft
			ans+=k-1;//return k
			ans+=2;//go to next k and push pu a stone to left
			ans+=2;//
			ans+=3*(r-1);
		}
		else{//first to right
			ans+=3*r;
			ans+=r;
			ans+=2;
			ans+=2;
			ans+=3*(l-1);
		}printf("%d\n",ans);
	}
}

C. Nastya Is Transposing Matrices(规律)

题目链接:http://codeforces.com/contest/1136/problem/C

题目大意:给出两个矩阵,判断第一个矩阵经过局部斜翻转之后能否变成第二个矩阵。可以输出YES,否则输出NO。

思路:这里说的翻转是沿着左上到右下的对角线进行,对称轴上的元素不变,对应的元素交换。然后发现还是个找规律的。因为斜对角线上的元素固定,所以所有的元素只会在同样的颜色的线之间来回变动,如图:所以我们只用比较这一对的就好了。

ACCode:

#include<stdio.h>
#include<iostream>
#include<string>
#include<algorithm>

#define ll long long
using namespace std;

const int MAXN=5e2+10;

ll a[MAXN][MAXN],b[MAXN][MAXN];
ll res[MAXN];
int n,m;

void Debug(){
	cout<<"Start Debug :"<<endl<<"a: "<<endl;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			cout<<a[i][j]<<" ";
		}cout<<endl;
	}cout<<"b:"<<endl;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			cout<<b[i][j]<<" ";
		}cout<<endl;
	}cout<<"End Debug"<<endl;
}
//	j 	j 	j
//i	1 	2 	3
//i	4 	5 	6
//i	7 	8 	9
//i	10 	11 	12
//
//	j 	j 	j	j
//i	1 	2 	3	10
//i	4 	5 	6	11
//i	7 	8 	9	12
void DealA(){
	for(int i=1,j,k;i<=n;++i){
		int ecnt=0,u;
		for(k=i,j=1;k>=1&&j<=m;--k,++j){
			res[++ecnt]=a[k][j];
		}sort(res+1,res+1+ecnt);
		for(k=i,j=1,u=1;k>=1&&j<=m&&u<=ecnt;--k,++j,++u){
			a[k][j]=res[u];
		}
	}
	for(int j=2,i,k;j<=m;++j){
		int ecnt=0,u;
		for(i=n,k=j;i>=1&&k<=m;--i,++k){
			res[++ecnt]=a[i][k];
		}sort(res+1,res+1+ecnt);
		for(i=n,k=j,u=1;i>=1&&k<=m&&u<=ecnt;--i,++k,++u){
			a[i][k]=res[u];
		}
	}
}
void DealB(){
	for(int i=1,j,k;i<=n;++i){
		int ecnt=0,u;
		for(k=i,j=1;k>=1&&j<=m;--k,++j){
			res[++ecnt]=b[k][j];
		}sort(res+1,res+1+ecnt);
		for(k=i,j=1,u=1;k>=1&&j<=m&&u<=ecnt;--k,++j,++u){
			b[k][j]=res[u];
		}
	}
	for(int j=2,i,k;j<=m;++j){
		int ecnt=0,u;
		for(i=n,k=j;i>=1&&k<=m;--i,++k){
			res[++ecnt]=b[i][k];
		}sort(res+1,res+1+ecnt);
		for(i=n,k=j,u=1;i>=1&&k<=m&&u<=ecnt;--i,++k,++u){
			b[i][k]=res[u];
		}
	}
}
int main(){
	while(~scanf("%d%d",&n,&m)){
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				scanf("%lld",&a[i][j]);
			}
		}
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				scanf("%lld",&b[i][j]);
			}
		}DealA();DealB();
		int flag=1;
		for(int i=1;i<=n;++i){
			for(int j=1;j<=m;++j){
				if(a[i][j]!=b[i][j]){
					flag=0;break;
				}
			}
			if(flag==0) break;
		}
		if(flag) printf("YES\n");
		else printf("NO\n");
	}
}

D. Nastya Is Buying Lunch(思维,找规律)

题目链接:http://codeforces.com/contest/1136/problem/D

题目大意:给出n个人,m个关系。下面按顺序给出n个人所处的位置。然后是m个关系。u v说明:如果u在v的前面一个位置,那么v可以和v进行换位。一个人A一开始在队尾,问他最多向前移动多少?

思路:因为u在v前面一个位置才能够换位,所以可以看成有向图。又发现如果前面的一个位置i可以和A所在的位置交换(A-i)次,那么A必定能够到达i这个位置。所以我们可以直接遍历,然后向前找,刷新能够到达的位置,并且刷新A所在的位置。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
  
#include<stdio.h>
#include<string.h> 
#include<math.h> 
   
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
  
#define ll long long 
#define Pair pair<int,int>
#define M_P(a,b) make_pair(a,b)
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=3e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;

struct Node{
	int v,val,nxt;
	Node(int _v=0,int _val=0,int _nxt=0){
		v=_v;val=_val;nxt=_nxt;
	}
};
Node Edge[MAXN<<1];
int Head[MAXN],Ecnt;
int a[MAXN],num[MAXN];
int n,m;

void Intt(){
	for(int i=1;i<=n;++i){
		Head[i]=-1;
	}Ecnt=0;
}
void Add(int u,int v,int val){
	Edge[Ecnt]=Node(v,val,Head[u]);
	Head[u]=Ecnt++;
}
int main(){
	scanf("%d%d",&n,&m);
	Intt();
	for(int i=1;i<=n;++i){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=m;++i){
		int u,v;scanf("%d%d",&u,&v);
		Add(v,u,1);
	}
	for(int i=Head[a[n]];i+1;i=Edge[i].nxt){
		int temp=Edge[i].v;
		num[temp]++;
	}int ans=0;
	for(int i=n-1;i>=1;--i){
		if(num[a[i]]==n-i-ans) ans++;
		else{
			for(int j=Head[a[i]];j+1;j=Edge[j].nxt){
				int temp=Edge[j].v;
				num[temp]++;
			}
		}
	}printf("%d\n",ans);
}

E. Nastya Hasn't Written a Legend(规律+二分+线段树)

题目链接:http://codeforces.com/contest/1136/problem/E

题目大意:给出n个数的数组A,然后是n-1个数的数组B,对于每个A[i+1]都满足A[i+1]>=A[i]+B[i]。有两个操作。

"+"操作:i位置的元素+x;"s"操作:求[l,r]区间内的元素和。

初始的A数组保证对于所有的A[i+1]>=a[i]+b[i];

思路:根据题目,我们可以这样化简:。然后就是普通线段树了。

因为.所以我们需要一个数组C来储存B的前缀和,用D来储存C的前缀和。

因为如果A[i+1]>A[i]+B[i];就不用对A[i+1]和A[i+1]后面的元素进行修改了。所以我们来确定修改的区间。因为初始A是一个有序的,我们维护之后也是有序的,因此可以用二分来找右端点。

剩下的就是普通线段树了。

ACCode:

//#pragma comment(linker, "/STACK:1024000000,1024000000")
  
#include<stdio.h>
#include<string.h> 
#include<math.h> 
   
#include<map>  
#include<set>
#include<deque> 
#include<queue> 
#include<stack> 
#include<bitset>
#include<string> 
#include<fstream>
#include<iostream> 
#include<algorithm> 
using namespace std; 
  
#define ll long long 
#define Pair pair<int,int>
#define M_P(a,b) make_pair(a,b)
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// ??
//std::ios::sync_with_stdio(false);
//  register
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;

ll Tree[MAXN<<2],Lazy[MAXN<<2];
ll a[MAXN],b[MAXN],c[MAXN],d[MAXN];
int n,q;

void Build(int l,int r,int rt){
	Lazy[rt]=-INF64;
	if(l==r){
		Tree[rt]=a[l];
		return ;
	}int mid=(l+r)>>1;
	Build(l,mid,rt<<1);Build(mid+1,r,rt<<1|1);
	Tree[rt]=Tree[rt<<1]+Tree[rt<<1|1];
}
void PushDown(int rt,int l,int r){
	if(Lazy[rt]!=-INF64){
		int mid=(l+r)>>1;
		int ln=mid-l+1,rn=r-mid;
		
		Tree[rt<<1]=Lazy[rt]*ln+(d[mid-1]-d[l-2]);
		Tree[rt<<1|1]=Lazy[rt]*rn+(d[r-1]-d[mid-1]);
		
		Lazy[rt<<1]=Lazy[rt<<1|1]=Lazy[rt];
		Lazy[rt]=-INF64;
	}
}
ll Query(int ql,int qr,int l,int r,int rt){
	if(ql<=l&&r<=qr) return Tree[rt];
	int mid=(l+r)>>1;
	PushDown(rt,l,r);
	ll ans=0;
	if(ql<=mid) ans+=Query(ql,qr,l,mid,rt<<1);
	if(qr>mid) ans+=Query(ql,qr,mid+1,r,rt<<1|1);
	return ans;
}
void Update(int ql,int qr,ll x,int l,int r,int rt){
	if(ql<=l&&r<=qr){
		Tree[rt]=(r-l+1)*x+(d[r-1]-d[l-2]);
		Lazy[rt]=x;
		return ;
	}int mid=(l+r)>>1;
	PushDown(rt,l,r);
	if(ql<=mid) Update(ql,qr,x,l,mid,rt<<1);
	if(qr>mid) Update(ql,qr,x,mid+1,r,rt<<1|1);
	Tree[rt]=Tree[rt<<1]+Tree[rt<<1|1];
}
void Refresh(int i,int x){
	int l=i,r=n,mid;
	ll key=Query(i,i,1,n,1);
	while(l<=r){
		mid=(l+r)>>1;
		ll temp=Query(mid,mid,1,n,1);
		//if(temp>key+x+c[mid-1]-c[i]). it's mean temp don't update.
		if(temp>key+x+c[mid-1]-c[i-1]) r=mid-1;
		else l=mid+1;
	}Update(i,r,key+x-c[i-1],1,n,1);
}
int main(){
	std::ios::sync_with_stdio(false);
	cin>>n;
	for(int i=1;i<=n;++i) cin>>a[i];
	for(int i=1;i<n;++i) cin>>b[i];
	for(int i=1;i<n;++i) c[i]=c[i-1]+b[i];
	for(int i=1;i<n;++i) d[i]=d[i-1]+c[i];
	Build(1,n,1);
	cin>>q;
	while(q--){
		string oper;int l,r;
		cin>>oper>>l>>r;
		if(oper=="+") Refresh(l,r);
		else cout<<Query(l,r,1,n,1)<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/89245889
今日推荐