暑假集训笔记

刷题刷的好累啊...不想刷题了...然后就来写题解了...

昨天晚上打了场div2..2000来名,加了155分....现在rating1281...我是菜鸡..暑假之前就打到了1200分以上了,结果暑假一掉再掉,直接掉到1100了...然后我就一直压力很大.......

昨天在机房打的..感觉很好,以后就在机房打吧....

其实昨天晚上能出D的,我的思路很对...但是当时没想太明白,还有20分钟的时候就去玩游戏了..

今天早上10分钟该出来了.....

我真的是吐了!!!没办法啊...人总要有遗憾的....

感觉还是比赛过程中感觉D出的太少了,就有点不想做了...

其实吧,赛后我感觉自己的实力已经完全能够出D题了....

不然感觉这场能加200多分...直接到1300+

Problem - C - Codeforces

昨天比赛的C题,刚开始的时候没啥思路....

看了样例想了一会,发现最后几个反转是最优的..

但到底反转几个呢..,看了几个样例发现反转log2(n)+1好像是最优的...

但是样例没过,卡在20了...这就尴尬了..

然后我就想着能不能枚举..

发现确实可以,n的范围为250,完全可以枚举!!!

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
typedef  unsigned long  long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int t;
int main(){
	scanf("%d",&t);
	while(t--){
		ll ans=0;
		ll n;
		scanf("%lld",&n);		
				
				
		for(int k=n;k>=1;k--){
			ll sum=0;
			ll maxn=0;
			ll j=n-k+1;
			
		for(ll i=n;i>=n-k+1;i--){
			maxn=max(maxn,i*j);
			sum=sum+i*j;
				j++;
			}
		
			for(ll i=1;i<=n-k;i++){	
				sum=sum+i*i;
			}
			ans=max(ans,sum-maxn);
		}
		
		printf("%lld\n",ans);
		
	}


	return 0;
}

 

Problem - D - Codeforces

比较可惜的一道题吧..感觉赛时能出的...

但是我区间合并的时候有点想错了..

我们对区间左端点从小到大排序,右端点从大到小排序,

对于正在处理的区间的左端点必须小于等于正在合并的区间的b的最大值,然后才能合并!!

这点确实比赛时候没有想清楚,今天早上想明白了.但感觉还剩20分钟应该能出来

然后就是二分了

我们可以发现一个规律:我们遍历已经合并的区间b的最大值一定是递增的!!

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
typedef  unsigned long  long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}

struct Node{
	ll l,r,a,b;
}s[200005];

struct Node1{
	ll left,right,a,b;
}d[200005];

bool cmp(Node s1,Node s2){
	if(s1.l!=s2.l)return s1.l<s2.l;
	return s1.r>s2.r;
}

int t;

int main(){
	
	scanf("%d",&t);
	
	while(t--){	
	
		int n;
		scanf("%d",&n);	
		for(int i=1;i<=n;i++){
			scanf("%lld%lld%lld%lld",&s[i].l,&s[i].r,&s[i].a,&s[i].b);
		}
			
		sort(s+1,s+1+n,cmp);
		
		int q;
		scanf("%d",&q);
		int cnt=1;
		
		d[1].left=s[1].l;
		d[1].right=s[1].r;
		d[1].a=s[1].a;
		d[1].b=s[1].b;
		
		for(int i=2;i<=n;i++){
			if(s[i].l<=d[cnt].b){
				d[cnt].right=max(d[cnt].right,s[i].r);
				d[cnt].a=min(d[cnt].a,s[i].a);
				d[cnt].b=max(d[cnt].b,s[i].b);
			}else{
				cnt++;
				d[cnt].left=s[i].l;
				d[cnt].right=s[i].r;
				d[cnt].a=s[i].a;
				d[cnt].b=s[i].b;
			}
		}
		
		
		while(q--){
			ll x;
			scanf("%lld",&x);
			int x1=1;
			int x2=cnt;
			ll ans=x;
			while(x1<=x2){
				int mid=(x1+x2)/2;
				if(d[mid].left<=x&&x<=d[mid].right){
					ans=max(ans,d[mid].b);
					x1=mid+1;
					continue;
				}
				if(x>d[mid].right)x1=1+mid;
				else x2=mid-1;
			}			
			
			printf("%lld ",ans);
			
		}
		printf("\n");
				
	}

	return 0;
}

 

Problem - C - Codeforces

一道双指针的题目..vp的时候感觉自己思路没啥问题...

我们通过样例发现长度为n的排列最小次数为n/2,

(昨天写的这里就手累的不得了了...就去跑路,感觉现在有时候敲字敲多了手是是真的疼!!)

如果n为偶数为6的话,依次交换3 4 2 5 16最少次,如果3 4一开始就在最前面就-1..

写着写着我突然知道自己哪里错了,如果n为8而且 情况为3 4  1 2  7 8  5 6然后最少的交换次数

2次..不一定只有 4 5在最前面才减少..

这好像就是题解的做法...我还是没有理解啊.题解啊!

题解:双指针

通过上面我们发现如果对于某个数k以及与他配对的n-k+1

如果k的位置>k-1的位置并且n-k+1为位置<n-k的位置那么左右指针移动

否则就停止

注意比较的是位置!!!

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
typedef  unsigned long  long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int t;
int main(){
	scanf("%d",&t);
	while(t--){
		int n;
		scanf("%d",&n);
		vector<int>a(n+5);
		for(int i=1;i<=n;i++){
			int x;
			scanf("%d",&x);
			a[x]=i;
		}
		
		int l=(n+1)/2;
		int r=(n+2)/2;
		while(l>=1&&(l==r||a[l]<a[l+1]&&a[r]>a[r-1])){
			l--;
			r++;
		}
		
		printf("%d\n",l);
	}


	return 0;
}

 

最近一直在打小白月赛...感觉之前的小白月赛都这么难的吗???

登录—专业IT笔试面试备考平台_牛客网

B题我都想了半天了..

如果l到r之间和为sum,如果sum%x==0,那么答案为0,否则答案就为1

答案为0很显然,就是答案为1如果证明,注意题目x范围0到(r−l+1)

设sum%x==n

如果n不为0,那么n+kx一定在l到r之间一定有解

登录—专业IT笔试面试备考平台_牛客网

小白月赛的C题没出来...我真是菜鸡..

一开始的思想就是素数筛筛素数...求vis[i],然后将a数组的vis[i]表示,如果b数组出现了就输出0

但是一直该不对..期间我还考虑了0的情况但是没仔细看题..ab数组都不能等于0.....

然后就看答案为..

思路也是素数筛的思想,素数筛+枚举每一个数的所有因子(1除外)(n*log2n)

不要用mp表示!!!mp查询的复杂度为O(logM)复杂度为(n*logn*logn)会超时

for(int i=2;i<=1000000;i++)
	{	int flag1=0;
		int flag2=0;
		for(int j=1;j*i<=1000000;j++){
			if(vis1[i*j])flag1=1;
			if(vis2[i*j])flag2=1;
		}
		if(flag1&&flag2){
			flag=1;
			break;
		}
	}
#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
typedef  unsigned long  long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int n;
int vis2[1000005];
int vis1[1000005];
int a[1000005];
int b[1000005];
int cnt=0;
int main(){
	int n;
	scanf("%d",&n);
	
	map<ll,ll>mp1,mp2;
	
	for(int i=1;i<=n;i++){
		a[i]=read();
		vis1[a[i]]=1;
	}
	
	for(int i=1;i<=n;i++){
		b[i]=read();
		vis2[b[i]]=1;
	}
	
	int flag=0;
	
	for(int i=2;i<=1000000;i++)
	{	int flag1=0;
		int flag2=0;
		for(int j=1;j*i<=1000000;j++){
			if(vis1[i*j])flag1=1;
			if(vis2[i*j])flag2=1;
		}
		if(flag1&&flag2){
			flag=1;
			break;
		}
	}
	 	
	
	if(flag){
		printf("No\n");
	}else{
		printf("Yes\n");
	}
	
	return 0;
}


登录—专业IT笔试面试备考平台_牛客网 

这题也没出来..太菜了

一直在想着如果利用等比数列算...

结果直接递推即可

树的高度为logkn!!总的复杂度为O(m*logkn)

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
typedef  unsigned long  long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int t;
int main(){
	scanf("%d",&t);
	while(t--){
		ll n,k,m;
		scanf("%lld%lld%lld",&n,&k,&m);
		for(int i=1;i<=m;i++){
			ll q;
			scanf("%lld",&q);
			if(k==1){
				printf("%lld\n",n-q);
				continue;
			}
			ll ans=1;
			ll left=k*q+1;
			ll right=k*q+k;
			while(1){
				if(left>=n)break;
				if(right>=n-1){
					ans=ans+n-1-left+1;
					break;
				}
				ans=ans+right-left+1;
				left=left*k+1;
				right=right*k+k;
			}
			printf("%lld\n",ans);
		}
	}

	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值