A
水题
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
LL n,k;
int main(){
cin>>n>>k;
vector<LL>fac;
for(LL i=1;i*i<=n;i++){
if(n%i==0){
fac.push_back(i);
if(i*i!=n)
fac.push_back(n/i);
}
}
sort(fac.begin(),fac.end());
if(k<=fac.size())
cout<<fac[k-1]<<endl;
else cout<<-1<<endl
else cout<<-1<<endl;;
return 0;
}
B
嗯……贪心
#include<bits/stdc++.h>
using namespace std;
const int maxn=3e5+5;
int a,b,c,m;
int u[maxn],p[maxn];
int main(){
scanf("%d%d%d%d",&a,&b,&c,&m);
for(int i=1;i<=m;i++){
int x;
char s[66];
scanf("%d%s",&x,s);
if(s[0]=='U'){
u[++u[0]]=x;
}else{
p[++p[0]]=x;
}
}
sort(u+1,u+1+u[0]);
sort(p+1,p+1+p[0]);
int cnt=0;
long long sum=0;
int cura=0,curb=0;
while(cura<u[0]&&a>0){
cnt++;
sum+=u[++cura];
a--;
}
while(curb<p[0]&&b>0){
cnt++;
sum+=p[++curb];
b--;
}
vector<int>vec;
for(int i=cura+1;i<=u[0];i++)vec.push_back(u[i]);
for(int i=curb+1;i<=p[0];i++)vec.push_back(p[i]);
sort(vec.begin(),vec.end());
for(int i=0;i<c&&i<vec.size();i++){
cnt++;
sum+=vec[i];
}
cout<<cnt<<" "<<sum<<endl;
return 0;
}
C
题意:给定两个串,在第二个串中删除尽量短的一个子串,使得剩余串是第一个串的一个子序列
题解:正反序贪心预处理子序列匹配处,枚举删除的右端点,二分找个最大的
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
char s1[maxn],s2[maxn];
int n,m;
int a[maxn],b[maxn];
vector<int>vec[256];
int main(){
scanf("%s%s",s1+1,s2+1);
n=strlen(s1+1);
m=strlen(s2+1);
for(int i=1;i<=n;i++){
vec[s1[i]].push_back(i);
}
for(int i=1;i<=m;i++){
int p=upper_bound(vec[s2[i]].begin(),vec[s2[i]].end(),a[i-1])-vec[s2[i]].begin();
if(p==vec[s2[i]].size())a[i]=n+1;
else a[i]=vec[s2[i]][p];
}
// for(int i=1;i<=m;i++)
// cout<<a[i]<<" \n"[i==m]; if(a[m]!=n+1){ puts(s2+1); return 0; } b[m+1]=n+1; for(int i=m;i>=1;i--){
int p=lower_bound(vec[s2[i]].begin(),vec[s2[i]].end(),b[i+1])-vec[s2[i]].begin()-1;
if(p<0)b[i]=0;
else b[i]=vec[s2[i]][p];
}
// for(int i=1;i<=m;i++)
// cout<<b[i]<<" \n"[i==m]; int l=1,r=m; for(int i=m+1;i>=1;i--){
int p=lower_bound(a+1,a+i,b[i])-a-1,nl,nr;
if(p<=0){
if(b[i]!=0)
nl=1,nr=i-1;
else continue;
}else{
nl=p+1,nr=i-1;
}
// cout<<p<<" "<<nl<<" "<<nr<<endl;
if(nl<=nr&&nr-nl<r-l){
r=nr;
l=nl;
}
}
if(l==1&&r==m)puts("-");
else{
for(int i=1;i<=m;i++)if(!(l<=i&&i<=r))
putchar(s2[i]);
puts("");
}
return 0;
}
D
题意:给定一个3xn的网格图,求一个从左上到右下最大的简单路径
题解:注意到如果往回走,存在一种最优情况,使得它最多向右走一格,(因为我们可以上下晃一下来减少两个)
所以可以用一种简单的插头dp,压记录一下右边三个插头,转移转移即可
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int maxn=1e5+5;
LL dp[maxn][6];
int n;
LL a[4][maxn];
void up(LL& x,LL y){
if(x<y)x=y;
}
int main(){
scanf("%d",&n);
for(int j=1;j<=3;j++)
for(int i=1;i<=n;i++){
scanf("%lld",&a[j][i]);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=6;j++)
dp[i][j]=-(1LL<<61);
}
dp[1][1]=a[1][1];
dp[1][2]=a[1][1]+a[2][1];
dp[1][3]=a[1][1]+a[2][1]+a[3][1];
dp[1][4]=a[1][1]+a[2][1]+a[3][1];
for(int i=1;i<n;i++){
up(dp[i+1][1],dp[i][1]+a[1][i+1]);
up(dp[i+1][2],dp[i][1]+a[1][i+1]+a[2][i+1]);
up(dp[i+1][3],dp[i][1]+a[1][i+1]+a[2][i+1]+a[3][i+1]);
up(dp[i+1][4],dp[i][1]+a[1][i+1]+a[2][i+1]+a[3][i+1]);
up(dp[i+1][1],dp[i][2]+a[1][i+1]+a[2][i+1]);
up(dp[i+1][2],dp[i][2]+a[2][i+1]);
up(dp[i+1][3],dp[i][2]+a[2][i+1]+a[3][i+1]);
up(dp[i+1][1],dp[i][3]+a[1][i+1]+a[2][i+1]+a[3][i+1]);
up(dp[i+1][2],dp[i][3]+a[2][i+1]+a[3][i+1]);
up(dp[i+1][3],dp[i][3]+a[3][i+1]);
up(dp[i+1][4],dp[i][3]+a[1][i+1]+a[2][i+1]+a[3][i+1]);
up(dp[i+1][1],dp[i][4]+a[1][i+1]+a[2][i+1]+a[3][i+1]);
up(dp[i+1][3],dp[i][4]+a[1][i+1]+a[2][i+1]+a[3][i+1]);
}
for(int i=1;i<=n;i++){
// for(int j=1;j<=5;j++)
// printf("%d ",dp[i][j]);
// puts("");
}
cout<<dp[n][3]<<endl;
return 0;
}
E
替罪羊重构的kdtree可以直接上
#include<bits/stdc++.h>
using namespace std;
int lans=0;
const int maxn=1e5+5;
int in(){
int x;scanf("%d",&x);
return x;
int r=0;char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))r=r*10+c-'0',c=getchar();
return r;
}
int n;
struct point{
int x,y,val;
int& operator[](const int s){return s==0?x:y;}
point(){val=1;}
point(int _x,int _y):x(_x),y(_y){val=1;}
}p[maxn];
struct rec{
int x[2],y[2];
rec(){}
rec(point a,point b){
x[0]=a.x;
x[1]=b.x;
y[0]=a.y;
y[1]=b.y;
}
rec(point p){x[0]=x[1]=p.x;y[0]=y[1]=p.y;}
};
bool operator==(const point &A,const point &B){
return A.x==B.x&&A.y==B.y;
}
inline rec operator+(const rec &ls,const rec &rs){
static rec R;R=ls;
R.x[0]=min(R.x[0],rs.x[0]);
R.x[1]=max(R.x[1],rs.x[1]);
R.y[0]=min(R.y[0],rs.y[0]);
R.y[1]=max(R.y[1],rs.y[1]);
return R;
}
inline bool operator*(const point &p,const rec &R){
return R.x[0]<=p.x&&p.x<=R.x[1]&&R.y[0]<=p.y&&p.y<=R.y[1];
}
inline bool In(const rec &A,const rec &B){
return B.x[0]<=A.x[0]&&A.x[1]<=B.x[1]&&B.y[0]<=A.y[0]&&A.y[1]<=B.y[1]; } inline bool Out(const rec &A,const rec &B){ return B.x[0]>A.x[1]||A.x[0]>B.x[1]||B.y[0]>A.y[1]||A.y[0]>B.y[1];
}
struct node{
rec R;point p;
int sum,siz;
node *c[2];
node *rz(){
sum=p.val;R=rec(p);siz=1;
if(c[0])sum+=c[0]->sum,R=R+c[0]->R,siz+=c[0]->siz;
if(c[1])sum+=c[1]->sum,R=R+c[1]->R,siz+=c[1]->siz;
return this;
}
node(){sum=0;siz=1;c[0]=c[1]=0;}
}*root,*re,pool[maxn],*cur=pool;
node *sta[maxn];
int D,si;
bool cmp(const point &A,const point &B){
if(D)return A.x<B.x||(A.x==B.x&&A.y<B.y);
return A.y<B.y||(A.y==B.y&&A.x<B.x); } int top; node *newnode(){ if(si)return sta[si--]; return cur++; } node* build(int l,int r,int d){ int mid=(l+r)>>1;D=d;
nth_element(p+l,p+mid,p+r+1,cmp);
node *t=newnode();t->p=p[mid];
if(l<=mid-1)t->c[0]=build(l,mid-1,d^1);
if(mid+1<=r)t->c[1]=build(mid+1,r,d^1);
return t->rz();
}
void dfs(node *&t){
if(t->c[0])dfs(t->c[0]);
p[++top]=t->p;
if(t->c[1])dfs(t->c[1]);
sta[++si]=t;*t=node();
//delete t;
}
node* rebuild(node *&t){
if(!t)return 0;
top=0;dfs(t);
return build(1,top,0);
}
#define siz(x) (x?x->siz:0)
void Add(node *&t,point p){
D^=1;
if(!t){t=newnode(),t->p=p;t->rz();return;}
if(t->p==p){t->p.val+=p.val;t->rz();return;}
if(p[D]<t->p[D])Add(t->c[0],p);
else Add(t->c[1],p);t->rz();
if(max(siz(t->c[0]),siz(t->c[1]))>0.7*t->siz)
re=t;
}
int Qans;
void Q(const node *t,const rec &R){
if(Out(t->R,R))return ;
if(In(t->R,R)){Qans+=t->sum;return;}
if(t->p*R)Qans+=t->p.val;
if(t->c[0])Q(t->c[0],R);
if(t->c[1])Q(t->c[1],R);
}
int k;
tuple<int,int,int> a[maxn];
int main(){
n=in();k=in();
for(int i=1;i<=n;i++){
get<1>(a[i])=in();
get<0>(a[i])=in();
get<2>(a[i])=in();
}
sort(a+1,a+1+n);
long long ans=0;
for(int i=n;i>=1;i--){
int r=get<0>(a[i]);
int x=get<1>(a[i]);
int f=get<2>(a[i]);
// cerr<<r<<" "<<x<<" "<<f<<endl;
int res=0;
Qans=0;
if(i!=n)Q(root,rec(point(x-r,f-k),point(x+r,f+k)));
res+=Qans;
//cerr<<res<<endl;
re=0;D=1;
Add(root,point(x,f));
if(re)rebuild(re);
ans+=res;
}
cout<<ans<<endl;
return 0;
}