您的位置:首页 > 其它

2017.10.19离线赛总结

2017-10-20 11:05 295 查看

vigenere ——4106

思路:水题,不解释。

game ——4107

思路:乍一看题意,求最大值最小,脑海中直接蹦出二分答案,然而看清楚题意,再看看数据范围,貌似可以贪心,且可以先估计按L或R 排序。

再仔细推出,答案应该是 max{∏ij=1Lj(Li∗Ri)} 。

根据式子,可以看出是按照L*R来排序的。

首先,我们只知道∏ni=1Li,那么,若最后一个与倒数第二个交换一下,就会发现ans变了,也经过2小时的对拍…可以说是正确的,应该也是显然的。(比赛贪心哪要这么多的证明)

#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)

#define N 1005
#define L 4005
#define P 10000
#define LL long long
using namespace std;
int n;
struct node{
int a,b,id;
bool operator<(const node &_)const{
return a*b<_.a*_.b;
}
}A
;

struct p60{
void chkmax(LL &x,LL y){
ed58
if(x<y)x=y;}
LL a,b,ans;
void solve(){
scanf("%lld%lld",&a,&b);
REP(i,1,n)scanf("%d%d",&A[i].a,&A[i].b);
sort(A+1,A+1+n);
REP(i,1,n){
LL res=a/A[i].b;
chkmax(ans,res);
a*=A[i].a;
}
cout<<ans<<endl;
}
}p60;

struct p100{
struct Big{
int num[L],len;
Big(){
memset(num,0,sizeof(num));
len=1;
}
Big operator *(const int &a)const{
Big b;
b.len=len;
REP(i,0,len-1){
int &B=b.num[i];
B+=num[i]*a;
if(B>=P)b.num[i+1]+=B/P,B%=P;
}
if(b.num[b.len])b.len++;
return b;
}
Big operator /(const int &a)const{
Big b;
REP(i,0,len-1)b.num[i]=num[i];
DREP(i,len-1,1)b.num[i-1]+=b.num[i]%a*P,b.num[i]/=a;
b.num[0]/=a;
b.len=len;
while(b.len>1 && !b.num[b.len-1])b.len--;
return b;
}
void Rd(){
char A[L];
scanf("%s",A);
int SL=strlen(A);
len=0;
for(int i=SL-1,res;res=0,i>=0;num[len++]=res,i-=4){
if(i>=3)for(int j=i-3;j<=i;j++)res=(res<<1)+(res<<3)+(A[j]^48);
else for(int j=0;j<=i;j++)res=(res<<1)+(res<<3)+(A[j]^48);
}
}
void Pr(){
printf("%d",num[len-1]);
DREP(i,len-2,0)printf("%04d",num[i]);
}
}Ans,Sum,Tmp;
void Max(Big &a,Big b){
if(b.len>a.len)a=b;
else if(a.len==b.len){
if(a.num[a.len-1]<b.num[b.len-1])a=b;
}
}
void solve(){
Sum.Rd();
LL b;cin>>b;
REP(i,1,n)scanf("%d%d",&A[i].a,&A[i].b);
sort(A+1,A+1+n);
REP(i,1,n){
Tmp=Sum;
Tmp=Tmp/A[i].b;
Max(Ans,Tmp);
Sum=Sum*A[i].a;
}
Ans.Pr();
}
}p100;
int main(){
//  freopen("game.in","r",stdin);
//  freopen("game.out","w",stdout);
scanf("%d",&n);
if(n<=100)p60.solve();
else p100.solve();
//  p100.solve();
return 0;
}


drive ——4108

思路:预处理倍增,然后模拟,与暴力思路类似。(然而暴力又没敲T_T)

#include<bits/stdc++.h>
#define REP(i,f,t) for(int i=(f),i##_end_=(t);i<=i##_end_;i++)
#define DREP(i,f,t) for(int i=(f),i##_end_=(t);i>=i##_end_;i--)
#define LL long long
#define INF 0x3f3f3f3f
#define N 100005
#define T 20

using namespace std;
int n,m;

int nxtb
,nxta
;

struct p70{
int h
;
void Init(){
REP(i,1,n-1){
int a=0,b=0,mn=INF;
REP(j,i+1,n){
int dx=abs(h[j]-h[i]);
if(dx<mn)mn=dx,a=j;
else if(dx==mn&&h[j]<h[a])a=j;
}
mn=INF;
REP(j,i+1,n){
if(j==a)continue;
int dx=abs(h[j]-h[i]);
if(dx<mn)mn=dx,b=j;
else if(dx==mn&&h[j]<h[b])b=j;
}
nxtb[i]=a;nxta[i]=b;
}
}
void solve(){
REP(i,1,n)scanf("%d",&h[i]);
int x0;cin>>x0;
Init();
int pos;
double mn=INF;
REP(i,1,n){
int f=1,beg=i,xi=x0;
LL l1=0ll,l2=0ll;
while(xi){
if(f){
if(!nxta[beg])break;
int dx=abs(h[beg]-h[nxta[beg]]);
if(dx>xi)break;
l1+=dx;xi-=dx;
beg=nxta[beg];
f=0;
}
else {
if(!nxtb[beg])break;
if(abs(h[beg]-h[nxtb[beg]])>xi)break;
l2+=abs(h[beg]-h[nxtb[beg]]);
xi-=abs(h[beg]-h[nxtb[beg]]);
beg=nxtb[beg];
f=1;
}
}
double tmp;
if(!l2){
tmp=INF;
if(tmp<mn)mn=tmp,pos=i;
else if(tmp==mn&&h[i]>h[pos])pos=i;
}
else {
tmp=double(l1*1.0/l2);
if(tmp<mn)mn=tmp,pos=i;
else if(tmp==mn&&h[i]>h[pos])pos=i;
}
}

printf("%d\n",pos);
cin>>m;
REP(i,1,m) {
int beg,xi;
scanf("%d%d",&beg,&xi);
int f=1;
LL l1=0ll,l2=0ll;
while(xi){
if(f){
if(!nxta[beg])break;
int dx=abs(h[beg]-h[nxta[beg]]);
if(dx>xi)break;
l1+=dx;xi-=dx;
beg=nxta[beg];
f=0;
}
else {
if(!nxtb[beg])break;
int dx=abs(h[beg]-h[nxtb[beg]]);
if(dx>xi)break;
l2+=dx;xi-=dx;
beg=nxtb[beg];
f=1;
}
}
printf("%lld %lld\n",l1,l2);
}
}
}p70;

LL fa
[T],fb
[T],f
[T];
struct node{
int h,id;
bool operator<(const node &a)const{
return h<a.h;
}
}A
;
set<node>S;
set<node>::iterator it;
struct car{
int id,dis;
bool operator<(const car &a)const{
if(dis==a.dis)return A[id].h<A[a.id].h;
else return dis<a.dis;
}
}tmp[10];
struct p100{
void Init(int i){
set<node>::iterator it=S.find(A[i]);
int cnt=0;
if(it!=S.begin()){
--it;
tmp[++cnt]=(car){it->id,abs(A[i].h-it->h)};
if(it!=S.begin()){
--it;
tmp[++cnt]=(car){it->id,abs(A[i].h-it->h)};
++it;
}
++it;
}
if((++it)!=S.end()){
tmp[++cnt]=(car){it->id,abs(A[i].h-it->h)};
if((++it)!=S.end())tmp[++cnt]=(car){it->id,abs(A[i].h-it->h)};
}
sort(tmp+1,tmp+1+cnt);
nxtb[i]=tmp[1].id;
if(cnt!=1)nxta[i]=tmp[2].id;
}
void work(int beg,int x,LL &l1,LL &l2){
DREP(j,T-1,0){
if(f[beg][j] && fa[beg][j]+fb[beg][j]<=x){
l1+=fa[beg][j],l2+=fb[beg][j];
x-=fa[beg][j]+fb[beg][j];
beg=f[beg][j];
}
}
int x1=nxta[beg];
if(!x1)return;
int d=abs(A[beg].h-A[x1].h);
if(d<=x)l1+=d;
}
void solve(){
REP(i,1,n)scanf("%d",&A[i].h),A[i].id=i;
S.insert(A
);
DREP(i,n-1,1)S.insert(A[i]),Init(i);
REP(i,1,n){
int x1=nxta[i],x2=nxtb[nxta[i]];
fa[i][0]=x1?abs(A[i].h-A[x1].h):0;
fb[i][0]=x2?abs(A[x1].h-A[x2].h):0;
f[i][0]=x2;
}
REP(j,1,T-1)
REP(i,1,n){
f[i][j]=f[f[i][j-1]][j-1];
fa[i][j]=fa[i][j-1]+fa[f[i][j-1]][j-1];
fb[i][j]=fb[i][j-1]+fb[f[i][j-1]][j-1];
}
int x0;
cin>>x0>>m;
LL ansa=1e18,ansb=0ll;
int pos=0;
REP(i,1,n){
LL l1=0ll,l2=0ll;
work(i,x0,l1,l2);
if (l2 && (!pos || l1*ansb<l2*ansa)){
ansa=l1;ansb=l2;
pos=i;
}
}
printf("%d\n",pos);
while(m--){
int beg,xi;
scanf("%d%d",&beg,&xi);
LL l1=0ll,l2=0ll;
work(beg,xi,l1,l2);
printf("%lld %lld\n",l1,l2);
}
}
}p100;
int main(){
//  freopen("drive.in","r",stdin);
//  freopen("drive.out","w",stdout);
cin>>n;
if(n<=1000)p70.solve();
else p100.solve();
return 0;
}


小结:这次考试暴力又没敲,实则就是自己不会打,而且第2题切分又切错了T_T…
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: