A题
传送门
模拟
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
#define gc getchar
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=1e5+5;
int n,x,y,a[N];
inline bool check(int p){
for(ri i=p+1,up=min(p+y,n);i<=up;++i)if(a[p]>a[i])return 0;
for(ri i=p-1,up=max(p-x,1);i>=up;--i)if(a[p]>a[i])return 0;
return 1;
}
int main(){
n=read(),x=read(),y=read();
for(ri i=1;i<=n;++i)a[i]=read();
for(ri i=1;i<=n;++i){
if(check(i))return cout<<i,0;
}
return 0;
}
B题
传送门
小学奥数题,勾股定理即可。
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
#define gc getchar
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=1e5+5;
int n,x,y,a[N];
inline bool check(int p){
for(ri i=p+1,up=min(p+y,n);i<=up;++i)if(a[p]>a[i])return 0;
for(ri i=p-1,up=max(p-x,1);i>=up;--i)if(a[p]>a[i])return 0;
return 1;
}
int main(){
double x=read(),y=read();
printf("%.10lf\n",(y*y-x*x)/(2.0*x));
return 0;
}
C题
传送门
一不小心
f
s
t
fst
fst了有点惨,计数排序+双指针即可,注意有可能爆
i
n
t
int
int需要特判。
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
#define gc getchar
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=4e5+5;
int n,I,a[N],b[N],m;
int main(){
n=read(),I=read();
for(ri i=1;i<=n;++i)a[i]=read();
sort(a+1,a+n+1);
int cnt=0,lim=1<<(min(20,(I*8)/n));
for(ri i=1;i<=n;++i){
if(a[i]^a[i-1])a[++cnt]=a[i],b[cnt]=1;
else ++b[cnt];
}
if(cnt<=lim)return cout<<0,0;
int sum=0,ans=0;
for(ri i=1;i<=lim;++i)sum+=b[i];
ans=sum;
for(ri i=lim+1;i<=cnt;++i){
sum-=b[i-lim],sum+=b[i];
ans=max(ans,sum);
}
cout<<n-ans;
return 0;
}
D题
传送门
大概是道线段树板题。。。
直接打全局标记+单点修改即可
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
#define gc getchar
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=2e5+5;
int n,a[N];
namespace sgt{
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (l+r>>1)
int mn[N<<2],tg[N<<2];
inline void pushnow(int p,int v){
tg[p]=max(tg[p],v);
mn[p]=max(mn[p],v);
}
inline void pushdown(int p){
if(tg[p])pushnow(lc,tg[p]),pushnow(rc,tg[p]),tg[p]=0;
}
inline void build(int p,int l,int r){
tg[p]=0;
if(l==r){mn[p]=a[l];return;}
build(lc,l,mid),build(rc,mid+1,r);
}
inline void modify(int p,int l,int r,int k,int v){
if(l==r){mn[p]=v;return;}
pushdown(p);
k<=mid?modify(lc,l,mid,k,v):modify(rc,mid+1,r,k,v);
}
inline void print(int p,int l,int r){
if(l==r){cout<<mn[p]<<' ';return;}
pushdown(p);
print(lc,l,mid);
print(rc,mid+1,r);
}
#undef lc
#undef rc
#undef mid
}
int main(){
n=read();
for(ri i=1;i<=n;++i)a[i]=read();
sgt::build(1,1,n);
for(ri op,p,x,tt=read();tt;--tt){
op=read();
if(op==1){
p=read(),x=read();
sgt::modify(1,1,n,p,x);
}
else{
x=read();
sgt::pushnow(1,x);
}
}
sgt::print(1,1,n);
return 0;
}
E题
传送门
考虑对于每一条输入的边判它连着的两个点是否已经被匹配,如果没有就把它们匹配并打上标记。
最后要么匹配数
≥
n
\ge n
≥n,要么独立集数
≥
n
\ge n
≥n
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
#define gc getchar
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=3e5+5,M=5e5+5;
int n,m,vis[N],in[N];
pii e[M];
int main(){
for(ri tt=read();tt;--tt){
n=read(),m=read();
vector<int>res;
res.clear();
for(ri i=1,up=3*n;i<=up;++i)vis[i]=0;
int cnt=0;
for(ri i=1;i<=m;++i){
e[i].fi=read(),e[i].se=read();
if(!vis[e[i].fi]&&!vis[e[i].se])vis[e[i].fi]=vis[e[i].se]=++cnt,res.push_back(i);
}
if(cnt>=n){
puts("Matching");
for(ri i=0;i<n;++i)cout<<res[i]<<' ';
puts("");
continue;
}
res.clear();
for(ri i=1,up=n*3;i<=up;++i)if(!vis[i])res.push_back(i);
puts("IndSet");
for(ri i=0;i<n;++i)cout<<res[i]<<' ';
puts("");
}
return 0;
}
F题
传送门
暴力
O
(
n
5
)
d
p
O(n^5)dp
O(n5)dp,Backseat-stargazer告诉了我一个
O
(
n
6
)
O(n^6)
O(n6)的做法然而被我叉掉了。。。
直接暴力
O
(
n
5
)
d
p
O(n^5)dp
O(n5)dp即可。
状态
f
x
1
,
y
1
,
x
2
,
y
2
f_{x_1,y_1,x_2,y_2}
fx1,y1,x2,y2表示把这个矩形填满的最小代价,然后枚举横着或者竖着切开的决策即可。
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
#define gc getchar
int ans=0;
char ch=gc();
while(!isdigit(ch))ch=gc();
while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
return ans;
#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=55;
int n,m,f[N][N][N][N],a[N][N];
char s[N];
inline int dfs(int x1,int y1,int x2,int y2){
if(~f[x1][y1][x2][y2])return f[x1][y1][x2][y2];
if(x1>x2||y1>y2)return f[x1][y1][x2][y2]=0;
if(x1==x2&&y1==y2)return f[x1][y1][x2][y2]=a[x1][y1];
int ret=max(x2-x1+1,y2-y1+1);
for(ri a=x1;a<x2;++a)ret=min(ret,dfs(x1,y1,a,y2)+dfs(a+1,y1,x2,y2));
for(ri b=y1;b<y2;++b)ret=min(ret,dfs(x1,y1,x2,b)+dfs(x1,b+1,x2,y2));
return f[x1][y1][x2][y2]=ret;
}
int main(){
n=read();
for(ri i=1;i<=n;++i){
scanf("%s",s+1);
for(ri j=1;j<=n;++j)a[i][j]=s[j]=='#';
}
memset(f,-1,sizeof(f));
cout<<dfs(1,1,n,n);
return 0;
}