第一次perf打满,好激动.
显然相邻段位的上下界差200.
然后…
int n; qr(n);
pr2((1999-n)/200+1);
已知 a , b , c , k a,b,c,k a,b,c,k.
你现在有 k k k次操作,每次使得一个数乘2.
问最后可不可能 c > b > a c>b>a c>b>a.
简单贪心.先让 b > a b>a b>a,再让 c > b c>b c>b.
int main() {
int a,b,c; qr(a); qr(b); qr(c);
int n; qr(n);
bool ans=1;
while(n--) {
if(b<=a) b*=2;
else c*=2;
}
if(c>b&&b>a) puts("Yes");
else puts("No");
return 0;
}
相邻两个的成绩有 k − 1 k-1 k−1个公共部分,比较不同的两个即可.
int n,m,a[N];
int main() {
qr(n); qr(m);
for(int i=1,x;i<=n;i++)qr(a[i]);
for(int i=m+1;i<=n;i++)
if(a[i]>a[i-m]) puts("Yes");
else puts("No");
return 0;
}
贪心,低价买高价卖.
int main() {
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]);
ll money=1000;
int i=1;while(i<=n) {
int j=i;
while(j<=n&&a[j+1]>=a[j])j++;
if(j>i)money=money/a[i]*a[j]+money%a[i];
i=j+1;
}
pr2(money); return 0;
}
简单状压.
定义 f [ i ] [ j ] f[i][j] f[i][j]表示状态 i i i, j j j条马路的最小代价.
首先,所有点求到 x , y x,y x,y轴的最小距离和.
然后我们每次考虑选择一些点计算贡献:
求贡献相当于求一下 x , y x,y x,y的中位数(相当于一个点上有很多个点)
然后求所有点到中位数的距离和即可.
我们预处理 w [ i ] w[i] w[i]表示状态 i i i的最小开销.
则可以得到 D P DP DP方程:
f [ i ] [ j ] = min { f [ k ] [ j − 1 ] + w [ i xor k ] } ( k & j = k ) f[i][j]=\min \{f[k][j-1]+w[i \operatorname{xor} k]\}(k\& j=k) f[i][j]=min{f[k][j−1]+w[ixork]}(k&j=k).
代码常数有点大…
#include
#define fi first
#define se second
#define lc (x<<1)
#define rc (x<<1|1)
#define gc getchar()//(p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2)?EOF:*p1++)
#define mk make_pair
#define pi pair
#define pb push_back
#define IT iterator
#define SZ(a) ((int)a.size())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N=17,size=1<<20,mod=998244353,inf=2e9;
//char buf[size],*p1=buf,*p2=buf;
template<class o> void qr(o &x) {
char c=gc; x=0; int f=1;
while(!isdigit(c)){if(c=='-')f=-1; c=gc;}
while(isdigit(c)) x=x*10+c-'0',c=gc;
x*=f;
}
template<class o> void qw(o x) {
if(x/10) qw(x/10);
putchar(x%10+'0');
}
template<class o> void pr1(o x) {
if(x<0)x=-x,putchar('-');
qw(x); putchar(' ');
}
template<class o> void pr2(o x) {
if(x<0)x=-x,putchar('-');
qw(x); puts("");
}
//math
ll mult(ll a,ll b,ll p) {
a=(a%p+p)%p; b=(b%p+p)%p;
ll c=(ld)a*b/p;
return a*b-c*p;
}
ll gcd(ll a,ll b) {return !a?b:gcd(b%a,a);}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
ll power(ll a,ll b=mod-2) {
ll c=1;
while(b) {
if(b&1) c=c*a%mod;
b /= 2; a=a*a%mod;
}
return c;
}
ll Power(ll a,ll b=mod-2) {
ll c=1;
while(b) {
if(b&1) c=mult(c,a,mod);
b /= 2; a=mult(a,a,mod);
}
return c;
}
ll n,x[N],y[N],p[N],w[1<<N],f[1<<N][N],lg[1<<N];
struct rec {
ll x,y;
bool operator <(rec b) const {
return x<b.x;
}
} a[N];
ll calc(int now) {
ll tot,s,ans=1e18,tmp,mid;
tot=s=0;
for(int i=0;i<n;i++)
if(now>>i&1) a[++tot]=(rec){x[i],p[i]},s+=p[i];
sort(a+1,a+tot+1);
mid=s+1>>1;
for(int i=1;i<=tot;i++)
if(mid<=a[i].y) {
tmp=0;
for(int j=1;j<=tot;j++) tmp+=a[j].y*abs(a[i].x-a[j].x);
ans=min(ans,tmp); break;
}
else mid-=a[i].y;
tot=s=0;
for(int i=0;i<n;i++)
if(now>>i&1) a[++tot]=(rec){y[i],p[i]},s+=p[i];
sort(a+1,a+tot+1);
mid=s+1>>1;
for(int i=1;i<=tot;i++)
if(mid<=a[i].y) {
tmp=0;
for(int j=1;j<=tot;j++) tmp+=a[j].y*abs(a[i].x-a[j].x);
ans=min(ans,tmp); break;
}
else mid-=a[i].y;
return ans;
}
int main() {
qr(n);
for(int i=0;i<=n;i++) lg[1<<i]=i;
for(int i=0;i<n;i++)
qr(x[i]),qr(y[i]),qr(p[i]);
int s=(1<<n)-1;
memset(f,63,sizeof f);
f[0][0]=0;
for(int i=1;i<=s;i++) {
f[i][0]=f[i&(i-1)][0];
int j=lg[i&-i];
f[i][0] += min(abs(x[j]),abs(y[j]))*p[j];
}
pr2(f[s][0]);
for(int i=1;i<(1<<n);i++) w[i]=calc(i);
for(int t=1;t<=n;t++) {
for(int i=1;i<=s;i++)
for(int j=i; ;j=(j-1)&i) {
f[i][t]=min(f[i][t],f[j][t-1]+w[i^j]);
if(!j) break;
}
pr2(f[s][t]);
}
return 0;
}
有 n ( n ≤ 2 ∗ 1 0 5 ) n(n\le 2*10^5) n(n≤2∗105)架飞机,现在已知他们的坐标和前进方向(上下左右),求最小撞机时间.
设0~3分别表示上下右左.以下简称向上的为0类点,以此类推.
撞击有两种:
第一种很容易处理,就是每个点按 x , y x,y x,y排序,判断 x o r y x ~or ~y x or y相同的情况.
观察第二种情况:两点间的斜率为 ± 1 \pm 1 ±1.
处理的时候我们是按 x x x坐标非降,即从左往右处理.
我们可以定义 f [ i ] [ 0 / 1 ] , g [ i ] [ 0 / 1 ] f[i][0/1],g[i][0/1] f[i][0/1],g[i][0/1].
f f f表示 2 2 2类点的贡献, g g g表示 0 / 1 0/1 0/1类点的贡献.
0 / 1 0/1 0/1分别表示斜率为 + 1 , − 1 +1,-1 +1,−1.
i i i表示的是直线的截距.
举个例子:
← ~~~~~\leftarrow ←
↑ ↑ ~\uparrow \uparrow ↑↑.
↑ ~\uparrow ↑
假如有两架飞机和向左的飞机相撞,那么为了求最小时间,
我们应该记录每个 截距and斜率 对应状态的最大 x x x坐标.
对于各类点的处理细节:
细节: y − x y-x y−x有可能下溢,所以给它加上 2 ∗ 1 0 5 2*10^5 2∗105.
#include
#define fi first
#define se second
#define lc (x<<1)
#define rc (x<<1|1)
#define gc getchar()//(p1==p2&&(p2=(p1=buf)+fread(buf,1,size,stdin),p1==p2)?EOF:*p1++)
#define mk make_pair
#define pi pair
#define pb push_back
#define IT iterator
#define SZ(a) ((int)a.size())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int N=4e5+10,size=1<<20,mod=998244353;
const ll inf=1e18;
template<class o> void qr(o &x) {
char c=gc; x=0; int f=1;
while(!isdigit(c)){if(c=='-')f=-1; c=gc;}
while(isdigit(c)) x=x*10+c-'0',c=gc;
x*=f;
}
template<class o> void qw(o x) {
if(x/10) qw(x/10);
putchar(x%10+'0');
}
template<class o> void pr1(o x) {
if(x<0)x=-x,putchar('-');
qw(x); putchar(' ');
}
template<class o> void pr2(o x) {
if(x<0)x=-x,putchar('-');
qw(x); puts("");
}
int n,dic[150],f[N*2][2],g[N*2][2];
ll ans=inf;
vector<pi> x[N],y[N];
int main() {
qr(n);
dic['U']=0;
dic['D']=1;
dic['R']=2;
dic['L']=3;
for(int i=1;i<=n;i++) {
int a,b,c;qr(a); qr(b);
char str[6]; scanf("%s",str);
a++; b++; c=dic[str[0]];
x[a].pb(mk(b,c));
y[b].pb(mk(a,c));
}
for(int i=1;i<N;i++) {
sort(all(x[i]));
sort(all(y[i]));
ll a,b;
a=b=inf;
for(auto j:x[i]) {
if(j.se==0) a=j.fi;
else if(j.se==1) b=j.fi;
if(a<b) ans=min(ans,(b-a)*5);
}
a=b=inf;
for(auto j:y[i]) {
if(j.se==2) a=j.fi;
else if(j.se==3) b=j.fi;
if(a<b) ans=min(ans,(b-a)*5);
}
}
for(int i=1;i<N;i++)
for(auto j:x[i]) {
int t=j.fi;
if(j.se==2) {
f[j.fi-i+N][0]=i;
f[j.fi+i][1]=i;
}
else if(j.se==3) {
int k=g[j.fi+i][1];
if(k) ans=min(ans,(i-k)*10LL);
k=g[j.fi-i+N][0];
if(k) ans=min(ans,(i-k)*10LL);
}
else if(j.se==1) {
int k=f[j.fi-i+N][0];
if(k) ans=min(ans,(i-k)*10LL);
g[j.fi+i][1]=i;
}
else if(j.se==0) {
int k=f[j.fi+i][1];
if(k) ans=min(ans,(i-k)*10LL);
g[j.fi-i+N][0]=i;
}
}
if(ans>inf/2) puts("SAFE");
else pr2(ans);
return 0;
}