A
二分最大距离。
/* Author : Rshs */
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int MXN = 1e6+5;
int n,c,x[MXN];
bool ck(int g){
int can=0,dis=0;
for(int i=2;i<=n;i++){
dis=dis+x[i]-x[i-1];
if(dis>=g) dis=0,can++;
}
return can>=c-1;
}
int main(){
while(cin>>n>>c){
for(int i=1;i<=n;i++)scanf("%d",&x[i]);
sort(x+1,x+1+n);
int l=0,r=1e9,ans=-1;
while(l<=r){
int md=(l+r)/2;
if(ck(md)) ans=md,l=md+1;
else r=md-1;
}
cout<<ans<<'\n';
}
return 0;
}
B
二分删几个。
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
int d[MXN];
char a[MXN],b[MXN];
int lea,leb;
int ck(int cd){
set<int>st;
for(int i=1;i<=cd;i++) st.insert(d[i]);
int pos=1;
for(int i=1;i<=leb;i++){
while(pos<=lea&&(st.find(pos)!=st.end()||a[pos]!=b[i])) pos++;
if(pos==lea+1) return 0;
pos++;
}
return 1;
}
int main(){
cin>>(a+1)>>(b+1);
lea=strlen(a+1),leb=strlen(b+1);
for(int i=1;i<=lea;i++) scanf("%d",&d[i]);
int l=0,r=lea,ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(ck(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
cout<<ans<<'\n';
return 0;
}
C
思路
因为飞船速度比公转速度快,所以可以二分。
二分到某个时刻:
计算出卫星p的终态,考虑以下三种情况:
第三种情况是两段切线+一段弧。
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const double pai = acos(-1.0L);
const double eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
int sx;
double xp,yp,vp,x,y,v,r,rp;
double xy_to_jiao(int xx,int yy){
double ax=abs(xx),ay=abs(yy);
if(ax==0&&yy==0) return 0;
if(ax==0&&yy>0) return pai/2.0;
if(ax==0&&yy<0) return -pai/2.0;
if(xx>=0&&yy>=0) return atan(ay/ax);
if(xx>=0&&yy<=0) return -atan(ay/ax);
if(xx<=0&&yy>=0) return pai-atan(ay/ax);
return -(pai-atan(ay/ax));
}
pair <double,double> jiao_to_xy(double Ejiao){
pair <double,double> re;
int cc=(int)(Ejiao/(2.0*pai));
Ejiao=Ejiao-(cc)*(2.0*pai);
if(Ejiao<-2.0*pai) Ejiao+=(2.0*pai);
if(Ejiao>2.0*pai) Ejiao-=(2.0*pai);
if(Ejiao>pai) Ejiao=Ejiao-(2.0*pai);
if(Ejiao<-pai) Ejiao=Ejiao+(2.0*pai);
if(Ejiao>=0&&Ejiao<=pai/(2.0)) {
re.FI=cos(Ejiao)*rp,re.SE=sin(Ejiao)*rp;
return re;
}
if(Ejiao>=pai/2.0&&Ejiao<=pai) {
Ejiao-=(pai/2.0);
re.SE=cos(Ejiao)*rp,re.FI=-sin(Ejiao)*rp;
return re;
}
if(Ejiao<=0&&Ejiao>=-pai/(2.0)) {
Ejiao=-Ejiao;
re.FI=cos(Ejiao)*rp,re.SE=-sin(Ejiao)*rp;
return re;
}
Ejiao=-Ejiao;
Ejiao-=(pai/2.0);
re.SE=-cos(Ejiao)*rp,re.FI=-sin(Ejiao)*rp;
return re;
}
bool xj(double npx,double npy){ //判断线段和圆有没有相交
double k=(npy-y)/(npx-x);
double b=(npx*y-x*npy)/(npx-x);
double aa=(1.0+k*k),bb=2.0*k*b,cc=b*b-r*r;
if(bb*bb-4.0*aa*cc<=0) return 0;
else {
double x1=(-bb-sqrt(bb*bb-4.0*aa*cc))/(2.0*aa);
double x2=(-bb+sqrt(bb*bb-4.0*aa*cc))/(2.0*aa);
if(npx<x1&&x<x1)return 0;
if(npx>x2&&x>x2)return 0;
}
return 1;
}
double dis(double a,double b,double c,double d) {
return sqrt((a-c)*(a-c)+(b-d)*(b-d));
}
bool ck(double tme){
double Ejiao=xy_to_jiao(xp,yp);
double Ajiao=vp*tme/(rp);
Ejiao+=Ajiao;
pair <double,double> xyzz=jiao_to_xy(Ejiao);
bool ju=xj(xyzz.FI,xyzz.SE);
if(ju==0){
return dis(xyzz.FI,xyzz.SE,x,y)/v<=tme;
}
double npx=xyzz.first,npy=xyzz.second;
double d1=dis(x,y,0,0),d2=dis(npx,npy,0,0);
double s1=sqrt(d1*d1-r*r);
double s2=sqrt(d2*d2-r*r);
double d3=dis(x,y,npx,npy);
double jj=acos(-(d3*d3-d1*d1-d2*d2)/(2.0*d1*d2))-asin(s1/d1)-asin(s2/d2); //那段弧对应的圆心角
double dd=s1+s2+jj*r;
return dd/v<=tme;
}
int main(){
//cout<<atan(8.1830416/5.7478)*10;
cin>>sx;xp=sx; cin>>sx;yp=sx; cin>>sx;vp=sx;
cin>>sx;x=sx; cin>>sx;y=sx; cin>>sx;v=sx; cin>>sx;r=sx;
rp=sqrt(xp*xp+yp*yp);
double l=0,r=1e16,ans=-1;
for(int _=1;_<=200;_++){
double mid=(l+r)/2.0;
if(ck(mid)) ans=mid,r=mid;
else l=mid;
}
printf("%.10lf",ans);
return 0;
}
D
按题意模拟,注意临界状态
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
int main(){
int w,h;cin>>w>>h;
int u1,d1,u2,d2;
cin>>u1>>d1>>u2>>d2;
if(d1<d2) swap(d1,d2),swap(u1,u2);
if(h>=d1){
while(h>=d1) w+=h,h--;
w=max(0,w-u1);
}
while(h>=d2) w+=h,h--;
w=max(0,w-u2);
while(h) w+=h,h--;
cout<<w<<'\n';
return 0;
}
E
尽量凑正方形
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
int main(){
int n;cin>>n;
int sq=sqrt(n);
if(n==sq*sq) return cout<<sq*2,0;
if(n<=sq*(sq+1)) return cout<<sq*2+1,0;
cout<<sq*2+2;
return 0;
}
F
多了就尽量删,少了就用一个*补齐
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
int main(){
string s;cin>>s;
int k;cin>>k;
int n=s.length();
int l=0;
for(int i=0;i<n;i++) if(s[i]!='?'&&s[i]!='*') l++;
if(k<l){
int del=l-k;
string ans;
for(int i=0;i<n;i++){
if(i<n-1&&del&&(s[i+1]=='*'||s[i+1]=='?')) i++,del--;
else if((s[i]!='*'&&s[i]!='?')) ans=ans+s[i];
//cout<<ans<<'\n';
}
if((int)ans.length()==k) cout<<ans<<'\n';
else cout<<"Impossible"<<'\n';
return 0;
}
int add=k-l;
string ans;
for(int i=0;i<n;i++){
if(i<n-1&&s[i+1]=='*') {
add++;
while(add) ans=ans+s[i],add--;
i++;
}
else if((s[i]!='*'&&s[i]!='?')) ans=ans+s[i];
}
if((int)ans.length()==k) cout<<ans<<'\n';
else cout<<"Impossible"<<'\n';
return 0;
}
G
max搞来搞去,尽量把深度低的结点赋予较大的值,保证所有和最小,注意从v到底一条链全部是-1的情况。
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
vector<int>g[MXN];
int s[MXN];
int mx[MXN];
int a[MXN];
int have[MXN];
void dfs(int now,int pre){
if(s[now]==-1)mx[now]=INT_MAX;
else mx[now]=s[now];
if(s[now]!=-1)have[now]=1;
for(auto v:g[now]){
if(v==pre) continue;
dfs(v,now);
have[now]=max(have[now],have[v]);
mx[now]=min(mx[now],mx[v]);
}
}
void gao(int now,int pre,int pa){
if(s[now]!=-1&&pa>s[now]) {puts("-1");exit(0);}
if(s[now]==-1) {
if(have[now]==0) a[now]=0;
else a[now]=max(mx[now]-pa,0);
}
else a[now]=s[now]-pa;
for(auto v:g[now]){
if(v==pre) continue;
gao(v,now,pa+a[now]);
}
}
int main(){
int n;cin>>n;
for(int i=2;i<=n;i++) {
int x;scanf("%d",&x);
g[i].push_back(x);
g[x].push_back(i);
}
for(int i=1;i<=n;i++)scanf("%d",&s[i]);
dfs(1,-1);
gao(1,-1,0);
LL ans=0;
for(int i=1;i<=n;i++) ans+=(LL)a[i];
cout<<ans<<'\n';
return 0;
}
H
思路
观察+证明 符合题意的矩阵:
行两个字母循环排列或者列两个字母循环排列,如:
CTCTC
AGAGA
TCTCT
AGAGA
或
ATGTG
GCACA
ATGTG
GCACA
ATGTG
得到这个结论后,枚举循环的那个东西,就变成了码农题了。
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
vector<char>a[MXN],ans[MXN],t[MXN];
char f[4]={'A','G','C','T'};
int g[MXN],mi=INT_MAX,u,ss1,ss2;
int n,m;
void work(int s1,int s2,int uu){
int ss[2][2]={s1,s2,-1,-1};
for(int i=0;i<4;i++) {
if(ss[0][0]!=i&&ss[0][1]!=i&&ss[1][0]==-1) ss[1][0]=i;
else {
if(ss[0][0]!=i&&ss[0][1]!=i&&ss[1][1]==-1) ss[1][1]=i;
}
}
for(int i=0;i<2;i++)for(int j=0;j<2;j++) ss[i][j]=f[ss[i][j]];
int cnt=0;
for(int i=1;i<=n;i++){
int c=0,cc=0;
for(int j=1;j<=m;j++)c=c+(ss[i%2][j%2]!=a[i][j]);
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
for(int j=1;j<=m;j++)cc=cc+(ss[i%2][j%2]!=a[i][j]);
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
cnt+=min(c,cc);
}
if(cnt<mi){
mi=cnt;
u=uu;
ss1=s1,ss2=s2;
}
}
int main(){
g['A']=0;g['G']=1;g['C']=2;g['T']=3;
cin>>n>>m;
for(int i=1;i<=n;i++){
a[i].push_back('*');
for(int j=1;j<=m;j++){
char x;cin>>x;
a[i].push_back(x);
}
}
for(int i=0;i<4;i++){
for(int j=0;j<4;j++) if(i!=j)work(i,j,0);
}
for(int i=1;i<=m;i++){
t[i].push_back('*');
for(int j=1;j<=n;j++){
t[i].push_back(a[j][i]);
}
}
for(int i=1;i<=n;i++)while(SZ(a[i])) a[i].pop_back();
for(int i=1;i<=m;i++){
a[i].push_back('*');
for(int j=1;j<=n;j++){
a[i].push_back(t[i][j]);
}
}
swap(n,m);
for(int i=0;i<4;i++){
for(int j=0;j<4;j++) if(i!=j)work(i,j,1);
}
swap(n,m);
int ss[2][2]={ss1,ss2,-1,-1};
for(int i=0;i<4;i++) {
if(ss[0][0]!=i&&ss[0][1]!=i&&ss[1][0]==-1) ss[1][0]=i;
else {
if(ss[0][0]!=i&&ss[0][1]!=i&&ss[1][1]==-1) ss[1][1]=i;
}
}
for(int i=0;i<2;i++)for(int j=0;j<2;j++) ss[i][j]=f[ss[i][j]];
if(u==0){
for(int i=1;i<=n;i++){
int c=0,cc=0;
for(int j=1;j<=m;j++)c=c+(ss[i%2][j%2]!=a[j][i]);
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
for(int j=1;j<=m;j++)cc=cc+(ss[i%2][j%2]!=a[j][i]);
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
if(c<cc){
for(int j=1;j<=m;j++)cout<<(char)ss[i%2][j%2];
}
else {
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
for(int j=1;j<=m;j++)cout<<(char)ss[i%2][j%2];
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
}
puts("");
}
}
else {
for(int i=1;i<=m;i++){
int c=0,cc=0;
for(int j=1;j<=n;j++)c=c+(ss[i%2][j%2]!=a[i][j]);
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
for(int j=1;j<=n;j++)cc=cc+(ss[i%2][j%2]!=a[i][j]);
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
if(c<cc){
for(int j=1;j<=n;j++) ans[j].push_back(ss[i%2][j%2]);
}
else {
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
for(int j=1;j<=n;j++) ans[j].push_back(ss[i%2][j%2]);
swap(ss[0][0],ss[0][1]);swap(ss[1][1],ss[1][0]);
}
}
for(int i=1;i<=n;i++) {
for(auto j:ans[i]) cout<<j;
puts("");
}
}
return 0;
}
I
树上博弈+线段树。
对于某一个结点V,他能得到的最大饼干数:
先将总时间减去到V的路径的两倍,再取路径上的若干吃的快的饼干,也就是前小(这部分可以用线段树维护)
然后考虑对弈情况:
Vasya肯定剪可以得到较大答案的边,所以后续遍历取儿子结点第二大的答案。
这里注意一个wa点:可能在根节点不动,只吃根节点的饼干。
(我也不知道为什么我要一开始写二分,还nm超时了(估计就超了2~3倍?))
/* Author : Rshs */
#include<bits/stdc++.h>
using namespace std;
#define FI first
#define SE second
#define LL long long
#define LDB long double
#define MP make_pair
#define PII pair<int,int>
#define SZ(a) (int)a.size()
const LDB pai = acos(-1.0L);
const LDB eps = 1e-10;
const LL mod = 1e9+7;
const int MXN = 1e6+5;
LL n,tme,x[200005],t[200005],d[200005],can[200005],dp[MXN];
vector<int>g[MXN];
LL S[MXN*4],C[MXN*4],MXT=1e6;
void update(int pos,int l,int r,int root,LL c){
if(l==r){
C[root]+=c;S[root]+=(c*(LL)l);
return ;
}
int mid=(l+r)/2;
if(pos<=mid) update(pos,l,mid,root<<1,c);
else update(pos,mid+1,r,root<<1|1,c);
C[root]=C[root<<1]+C[root<<1|1];
S[root]=S[root<<1]+S[root<<1|1];
}
LL query(int l,int r,int root,LL have){
if(l==r){
return min(have/(LL)l,C[root]);
}
int mid=(l+r)/2;
if(S[root<<1]>have) return query(l,mid,root<<1,have);
return query(mid+1,r,root<<1|1,have-S[root<<1])+C[root<<1];
}
void dfs(int now,int pre,LL co){
update(t[now],1,MXT,1,x[now]);
can[now]=query(1,MXT,1,tme-co);
for(auto i:g[now]){
if(i==pre)continue;
dfs(i,now,co+d[i]*2LL);
}
update(t[now],1,MXT,1,-x[now]);
}
void gao(int now,int pre){
if(SZ(g[now])==1) {
dp[now]=can[now];return;
}
multiset<LL>st;
for(auto i:g[now]){
if(i==pre)continue;
gao(i,now);
st.insert(dp[i]);
}
st.erase(--st.end());
if(SZ(st)!=0) dp[now]=max(can[now],*(--st.end()));
else dp[now]=can[now];
}
int main(){
cin>>n>>tme;
for(int i=1;i<=n;i++) {int sa;scanf("%d",&sa);x[i]=sa;}
for(int i=1;i<=n;i++) {int sa;scanf("%d",&sa);t[i]=sa;}
for(int i=2;i<=n;i++){
int sa;scanf("%d",&sa); g[sa].push_back(i);g[i].push_back(sa);
int sb;scanf("%d",&sb); d[i]=sb;
}
dfs(1,-1,0);
LL ans=min(tme/t[1],x[1]);
for(auto i:g[1]){
gao(i,1);
ans=max(ans,dp[i]);
}
cout<<ans<<'\n';
return 0;
}
/*
5 4
1 5 1 7 7
1 3 1 2 2
1 1
1 1
2 0
2 0
*/