刷题刷的好累啊...不想刷题了...然后就来写题解了...
昨天晚上打了场div2..2000来名,加了155分....现在rating1281...我是菜鸡..暑假之前就打到了1200分以上了,结果暑假一掉再掉,直接掉到1100了...然后我就一直压力很大.......
昨天在机房打的..感觉很好,以后就在机房打吧....
其实昨天晚上能出D的,我的思路很对...但是当时没想太明白,还有20分钟的时候就去玩游戏了..
今天早上10分钟该出来了.....
我真的是吐了!!!没办法啊...人总要有遗憾的....
感觉还是比赛过程中感觉D出的太少了,就有点不想做了...
其实吧,赛后我感觉自己的实力已经完全能够出D题了....
不然感觉这场能加200多分...直接到1300+
昨天比赛的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;
}
比较可惜的一道题吧..感觉赛时能出的...
但是我区间合并的时候有点想错了..
我们对区间左端点从小到大排序,右端点从大到小排序,
对于正在处理的区间的左端点必须小于等于正在合并的区间的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;
}
一道双指针的题目..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;
}
最近一直在打小白月赛...感觉之前的小白月赛都这么难的吗???
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之间一定有解
小白月赛的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;
}
这题也没出来..太菜了
一直在想着如果利用等比数列算...
结果直接递推即可
树的高度为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;
}