写到第100000B次还在写Div2的感觉着实有点丢人…… 只能怪我的成长速度不如cf的题目难度提升速度了……
果然,还是太弱了……
这次绝对觉得E题是非常有希望出的,结果果然还是想多了……就算到现在都是出AC的最少的题…… 事实是白白消耗了比赛中七成的时间……
我们选取最中间的一个数,偶数的话取中位数左右两侧任意选一个,它就是MID,放在末尾的那个了,一边儿呆着去,然后从这个MID的左右开始,左一个,右一个,左一个,右一个,直到放完(这里要注意哦,左右有的时候不会同时取完哦,当n是偶数的时候一边会比另一边多一个),当(左边到了0&&右边到了n)的时候,结束for,把MID输出出来。ok啦~啊对了,n=2的时候除外哦。
Code:
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
bool cmp(const int a, const int b)
{
return a > b;
}
int main()
{
int n; cin>>n;
if(n==1 || n==2) cout<<1<<endl<<1<<endl;
else if(n==3) cout<<2<<endl<<"1 3"<<endl;
else
{
printf("%d\n",n);
int mid=n/2+1;
for(int i=1;mid-i>0 || mid+i<=n;i++)
{
if(mid-i>0) printf("%d ",mid-i);
if(mid+i<=n) printf("%d ",mid+i);
}
printf("%d",n/2+1);
}
return 0;
}
初速度是v1,末速度是v2,这个车最快的速度变量(注意不是加速度,这车的速度是瞬间变化的,厉害吧)绝对值不大于d,问在t秒的范围内,车最多走多远。
我们知道,总路程=Sum(每秒钟的当前秒速)
所以在保证每两个相邻秒内速度差的绝对值不大于d的同时,尽可能让他们大,就行了。
据说叫尺取法?这个名词没有很懂呢,有懂的麻烦告诉我一声哦~
我是在起点和终点两端开始,同时向中间走,每次+d,到了中间碰头(啊奇数的时候我处理了一下,左边的递增序列拿到中位数的那个点),然后开始while(1)判断,当左线的末端与右线的末端差值的绝对值不大于d时结束。否则哪边高了哪边就退一步让矮的那边来升一步,这道题说一定有解就说明这种方法一定会获得解,如果不一定有解的话,聪明的小读者(哈哈哈我早就想这么说一次了)你们会进行怎样的改动呢?
Code:
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
bool cmp(const int a, const int b)
{
return a > b;
}
int v[128]={0};
int getsum(int t)
{
int s=0; //就这里忘了初始化0,就给我算错么Q^Q
for(int i=0;i<t;i++)
{
s+=v[i];
//cout<<i<<":"<<v[i]<<endl;
}
return s;
}
int main()
{
int v1=0,v2=0,t=0,d=0,l=0,r=0;
scanf("%d%d%d%d",&v1,&v2,&t,&d);
v[0]=v1,v[t-1]=v2,r=t-1;//r=t-1 forgotten
for(int i=1;i<t-i-1;i++)
{
l=i,r=t-i-1;
v[l]=v[l-1]+d;
v[r]=v[r+1]+d;
//cout<<v[l]<<":"<<v[r]<<endl;
}
if(t%2)
{
l++;
v[l]=v[l-1]+d;
}
//cout<<l<<":"<<r<<endl;
while(abs(v[l]-v[r])>d)
{
if(v[l]>v[r]) v[l--]=v[r--]+d;
else v[r++]=v[l++]+d;
}
cout<<getsum(t)<<endl;
return 0;
}
然后告诉你每个骰子的最大点数di(意为他们的点数只能在1-di间取得)。问,对于每个骰子,它绝对不可能是的点数有多少种情况。
我们记di的总和为s
我们要这么想:对于某个骰子,除去它以外,别的骰子的点数和的取值区间,应该是不小于骰子数(n-1),不大于除去当前骰子以外的最大点数和(s-di),能想到这一步的话,不能掷出的点数种类数就明了了吧?好吧还是不清楚么?当前骰子总共有di种点数,其中它不能太小,小到其它骰子都是最大点数都不够到A,也不能太大,大到其他骰子都是最小点数1也超过A了。
Code:
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
bool cmp(const int a, const int b)
{
return a > b;
}
int n=0,d[200086]={0};
ll a=0,b[200086]={0},s=0;
int main()
{
scanf("%d%I64d",&n,&a);
for(int i=0;i<n;i++)
{
scanf("%d",&d[i]);
s+=d[i];
}
for(int i=0;i<n;i++)
{
//不能取的有两种情况:
ll si=a-s+d[i]-1; //small_impossible=其他都取最大时,不能小于某值
ll bi=d[i]-a+n-1;//big_impossible=其他都取最小值1时,不能大于某值
ll ai=0LL; //all_impossible
if(si>=0 && bi>=0) ai=si+bi;
else if(si>=0) ai=si;
else if(bi>=0) ai=bi;
else ai=0LL;
b[i]=max(0LL,ai);
printf("%I64d",b[i]);
if(i<n-1)printf(" ");
}
return 0;
}
以及悲惨的自以为能过的E题……
因为错了还是不说解题思路了,因为可能思路就是错的……
Code:
#include <cmath>
#include <cctype>
#include <cstdio>
#include <string>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
bool cmp(const int a, const int b)
{
return a > b;
}
ll ans=0LL,tmp=0LL;
ll dp[200086]={0};
int mrk[200086]={0},tmrk[200086]={0};
int main()
{
int n=0, now=0, i=0; cin>>n;
for(i=1;i<=n;i++)
{
scanf("%I64d",&dp[i]);
}
int m=0; cin>>m;
for(i=0;i<m;i++)
{
scanf("%d",&now);
mrk[now]++;
tmrk[now]++;
}
if(n==2)
{
printf("%I64d",(dp[2]-dp[1])*(mrk[1]+mrk[2]-1));
return 0;
}
int mr=min(mrk[1],mrk[n]);
for(int i=2;i<=n-1;i++)
{
tmrk[i]/=2;
mr=min(mr,tmrk[i]);
}
if(mrk[1]>1 || mrk[n]>1 || mr>=1)
{
int round=min(mrk[1],mrk[n]);
round=min(mr,round);
mrk[1]-=round; mrk[n]-=round;
for(int i=2;i<=n-1;i++)
mrk[i]-=round*2;
ans+=(dp[n]-dp[1])*2*round;
// cout<<round<<":"<<mrk[1]<<mrk[2]<<mrk[3];
// cout<<"now"<<ans<<endl;
}
if(m==n*2-2)
{
ll dist=dp[2]-dp[1];
if(n!=2) for(int i=3;i<=n;i++)
{
if(dp[i]-dp[i-1]!=dist)
{
printf("-1");
return 0;
}
}
cout<<(ll)(dp[n]-dp[1])*2LL-dist<<endl;
return 0;
}
int f1=0,f2l=0,f2r=0;
int l1=0,l2=0,
r1=0,r2=0;
i=1; while(mrk[i]==0)i++;
if(mrk[1]==1 && mrk[2]==2)
{
mrk[1]=2;
f2l=l2=1;
while(mrk[l2]==2 && l2<=n)l2++;l2--;
}
if(mrk[n]==1 && mrk[n-1]==2)
{
mrk[n]=2;
f2r=1;
r2=n;
while(mrk[r2]==2 && r2>=1)r2--;r2++;
}
for(i=max(l2,i);i<=n;i++)
{
if(f1==0 && mrk[i]==1)
{
f1=1;
l1=r1=i;
while(mrk[r1]==1 && r1<=n) r1++;r1--;
}
}
//ALL l2===================r2 <already considered>
//f2l\f2r\f1 =========l2/l1--------------r1/r2============
//f2l ==========l2
//f2r r2==========
//f1\f2r l1-------------r1/r2=============
//f1\f2l ============l2/l1------------
//f1 l1---------------------l2
//cout<<l1<<":"<<r1<<" "<<l2<<":"<<r2<<endl;
if(f1) ans+=(ll)(dp[r1]-dp[l1]);
if(f2l) ans+=(ll)(dp[l2]-dp[1])*2LL;
if(f2r) ans+=(ll)(dp[n]-dp[r2])*2LL;
if(f1&&f2l) ans+=(ll)(dp[l1]-dp[l1-1]);
if(f1&&f2r) ans+=(ll)(dp[r1+1]-dp[r1]);
cout<<ans<<endl;
return 0;
}