题目链接
C-装备合成
题意:
做法:
我也不知道为什么可以三分,至今没懂,题解就是这么说的,(你个嘚嘚)大概就是下面的方程会得到z的一个抛物线的图:
n1*(2a+3b)<=x
n2*(4a+b)<=y
z=n1+n2
我的三分怎么写怎么wa,参考了题解的代码。。。
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=2e5+10;
int x,y,mi,ans;
int cal(int num,int x,int y)
{
return num+min((x-2*num)/4,y-3*num);
}
int main()
{
int _;cin>>_;while(_--)
{
scanf("%d%d",&x,&y);
int l=0,r=min(x/2,y/3),ans;
while(l+10<=r)
{
int m1=l+r>>1,m2=m1+r>>1;
if(cal(m1,x,y)>=cal(m2,x,y)) r=m2-1,ans=m1;
else l=m1+1;
}
int m1=ans;
//printf("m1:%d\n",m1+min(x-2*mi,y-3*mi));
int res=0;
for(int i=l;i<=r;i++)
res=max(res,i+min((x-2*i)/4,y-3*i));
printf("%d\n",res);
}
}
E-石子搬运
扫描二维码关注公众号,回复: 10150389 查看本文章想到dp[i][j]为i堆石头 搬j次的最小花费,再想到两两合并没有先后顺序,所以就可以采用线段树合并dp即可
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=(b);++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define pb push_back
#define pi pair<int, int>
#define mk make_pair
using namespace std;
typedef long long ll;
ll gcd(ll a,ll b) { return b?gcd(b,a%b):a;}
const int N=4e2+10;
ll dp[4*N][N];
ll n,m,a[N],len[4*N];
ll sum=0;
void push(int id)
{
memset(dp[id],0x3f3f3f3f,sizeof(dp[id]));
int ls=id<<1,rs=id<<1|1;
for(int i=len[ls];i<=m;++i){
for(int j=len[rs];i+j<=m;++j){
dp[id][i+j]=min(dp[id][i+j],dp[ls][i]+dp[rs][j]);
}
}
}
void build(int id,int l,int r)
{
len[id]=r-l+1;
if(l==r){
for(int i=1;i<=min(a[l],m);++i){
ll v=a[l]/i;
dp[id][i]=a[l]%i*(v+1)*(v+1)+(i-a[l]%i)*v*v;
}
return ;
}
int mid=l+r>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
push(id);
}
void up(int id,int l,int r,int pos,ll v)
{
if(l==r){
a[l]=v;
memset(dp[id],0x3f3f3f3f,sizeof(dp[id]));
for(int i=1;i<=min(a[l],m);++i){
ll v=a[l]/i;
dp[id][i]=a[l]%i*(v+1)*(v+1)+(i-a[l]%i)*v*v;
}
return ;
}
int mid=l+r>>1;
if(pos<=mid) up(id<<1,l,mid,pos,v);
else up(id<<1|1,mid+1,r,pos,v);
push(id);
}
int main()
{
cin>>n>>m;
rep(i,1,n) {
scanf("%lld",&a[i]);
sum+=a[i];
}
memset(dp,0x3f3f3f3f,sizeof(dp));
build(1,1,n);
int q;
scanf("%d",&q);
while(q--)
{
int id;
ll v;
scanf("%d%lld",&id,&v);
sum=sum-a[id]+v;
up(1,1,n,id,v);
printf("%lld\n",dp[1][min(sum,m)]);
}
}