题目来源:https://atcoder.jp/contests/abc153
寒假太颓废了,一直没怎么写题,然后差点凉在了第二题 题目看错了 。还有当时最后一题我不会… 不过补上了 还是学到了点技巧的 【差分】 如果我打了那场估计就上分啦
水题
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n); r(m);
int ans=n/m;
if(n%m!=0) ans++;
cout<<ans<<endl;
return 0;
}
这题我题目居然看错了,丢人
就是减去所有的 看看是否小于等于0就好了 也是水题…
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n); r(m);
while(m--){
int a; r(a);
n-=a;
}
if(n<=0) cout<<"Yes\n";
else cout<<"No\n";
return 0;
}
这题贪一下心就行,把血最多的先秒掉,剩下的小的加起来就是答案
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
int f[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n); r(m);
LL ans=0;
FOR(i,1,n){
r(f[i]);
}
sort(f+1,f+n+1);
FOR(i,1,n-m){
ans+=f[i];
}
cout<<ans<<endl;
return 0;
}
这题有公式的
h=1 1次攻击即可 【1=21-1】
h=2 1次攻击分裂成 2个h=1 再攻击2次 【1+2=22-1】
h=3 同2 【1+2=22-1】
h=4 1次攻击分裂成 2个h=2 再攻击2次分裂成 4个h=1 再攻击4次 【1+2+4=23-1】
而指数就是log2(h)+1
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
LL f[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(n);
f[0]=1;
FOR(i,1,60){
f[i]=f[i-1]*2;
}
FOR(i,0,60){
if(n<f[i]){
cout<<f[i]-1<<endl;
break;
}
}
return 0;
}
这题我用DP写的,写出来了感觉人很舒服233
这就可以理解为背包问题,每一件物品可以拿无数次,重量是a,花费是b,要让花费最少。
但也不是一成不变的,改了一丢丢。 我们令dp[ i ]表示达到重量i所需的最少花费
那最后的答案在dp[ H ] 和 dp[ H + 1e4 ]中取最小值就好了
注意不是dp[ H ] 到 dp[ 2*H ]中取 可能有的花费很小但重量远大于H
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
int f[N];
int dp[N];
int w[N],v[N];
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
r(m); r(n);
FOR(i,1,n){
r(v[i]);
r(w[i]);
}
FOR(i,1,m+1e4) dp[i]=2e9;
dp[0]=0;
FOR(i,1,n){
for(int j=v[i];j<=m+1e4;j++){
// cout<
dp[j]=min(dp[j],dp[j-v[i]]+w[i]);
}
}
int ans=2e9;
FOR(i,m,m+1e4){
ans=min(dp[i],ans);
}
cout<<ans<<endl;
return 0;
}
最后一题我确实收获到了 差分的技巧
首先这题每次要找到最左边的坐标l 那每次操作就是取[l l+2*D] 这是贪心的思想
怎么找到这区间里面的怪物呢? 我们可以二分找到区间最右边的怪物坐标 r
但是具体怎么让这个区间的所有怪物扣血呢? 差分!
比如说你想让[ l , r ]都减去 t 那你可以滚一个前缀和 让q[ l ] - = t ,q[ r+1 ] + =t
然后循环让q[l]+=q[l-1] 这样就实现了减t
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=998244353;
const double eps=1e-8;
const double pi=acos(-1);
LL n,m;
struct node
{
int x,v;
}f[N];
LL sum[N];
bool cmp(node a,node b)
{
return a.x<b.x;
}
template<class T>
inline void read(T &x)
{
char c; x=1;
while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
T res=c-'0';
while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
x*=res;
}
int main()
{
int a;
rrr(n,m,a);
FOR(i,1,n){
r(f[i].x); r(f[i].v);
}
sort(f+1,f+n+1,cmp);
LL now=0;
LL ans=0;
FOR(i,1,n){
sum[i]+=sum[i-1];
f[i].v+=sum[i];
if(f[i].v<=0) continue;
int l=i,r=n,res;
while(l<=r){
int mid=(l+r)>>1;
if(f[mid].x<=f[i].x+2*m){
res=mid;
l=mid+1;
}
else r=mid-1;
}
//i ---- ans 都要-
int t=f[i].v/a;
if(f[i].v%a) t++;
ans+=t;
sum[i]-=t*a;
sum[res+1]+=t*a;
}
cout<<ans<<endl;
return 0;
}
啥时候才可以不看题解 AK ABC ,555