比赛过题:ABCEFGH
赛后补题:D
A
签到
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=55;
vector<int> a[N];
vector<int> b[N];
vector<int> c[N];
int l[N];
void init()
{
for(int i=0;i<N;i++)
{
a[i].clear();
b[i].clear();
c[i].clear();
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
int n,m;
scanf("%d%d",&n,&m);
for(int i=0;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
a[x].push_back(y);
}
for(int i=0;i<m;i++)
{
int x,y;
scanf("%d%d",&x,&y);
b[x].push_back(y);
}
for(int i=0;i<N;i++)
{
for(int j=0;j<a[i].size();j++)
for(int k=0;k<b[a[i][j]].size();k++)
c[i].push_back(b[a[i][j]][k]);
sort(c[i].begin(),c[i].end());
l[i]=unique(c[i].begin(),c[i].end())-c[i].begin();
}
for(int i=0;i<N;i++)
{
for(int j=0;j<l[i];j++)
printf("%d %d\n",i,c[i][j]);
}
}
}
B
计算几何
#include <cstdio>
#include <cmath>
#include <iostream>
using namespace std;
typedef long long ll;
typedef long double ld;
const ld eps=1e-8;
struct point{
ld x,y;
point(){}
point(ld X,ld Y){
x=X;y=Y;
}
point operator -(const point &b)const{
return point(x - b.x,y - b.y);
}
//叉积
ld operator ^(const point &b)const{
return x*b.y - y*b.x;
}
//点积
ld operator *(const point &b)const{
return x*b.x + y*b.y;
}
}sd,td;
struct san{
point p[3];
}s,t;
int T,x,y;
int sgn(ld x){
if(fabs(x) < eps)return 0;
if(x < 0)return -1;
else return 1;
}
struct line{
point s,e;
line(){}
line(point _s,point _e){
s = _s;e = _e;
}
pair<int,point> operator &(const line &b)const{
point res = s;
if(sgn((s-e)^(b.s-b.e)) == 0){
if(sgn((s-b.e)^(b.s-b.e)) == 0)
return make_pair(0,res);//重合
else return make_pair(1,res);//平行
}
ld t = ((s-b.s)^(b.s-b.e))/((s-e)^(b.s-b.e));
res.x += (e.x-s.x)*t;
res.y += (e.y-s.y)*t;
return make_pair(2,res);
}
};
bool OnSeg(point P,line L){
return
sgn((L.s-P)^(L.e-P)) == 0 &&
sgn((P.x - L.s.x) * (P.x - L.e.x)) <= 0 &&
sgn((P.y - L.s.y) * (P.y - L.e.y)) <= 0;
}
bool inter(line l1,line l2){
return max(l1.s.x,l1.e.x) >= min(l2.s.x,l2.e.x) &&
max(l2.s.x,l2.e.x) >= min(l1.s.x,l1.e.x) &&
max(l1.s.y,l1.e.y) >= min(l2.s.y,l2.e.y) &&
max(l2.s.y,l2.e.y) >= min(l1.s.y,l1.e.y) &&
sgn((l2.s-l1.e)^(l1.s-l1.e))*sgn((l2.e-l1.e)^(l1.s-l1.e)) <= 0 &&
sgn((l1.s-l2.e)^(l2.s-l2.e))*sgn((l1.e-l2.e)^(l2.s-l2.e)) <= 0;
}
bool solve(san u,san v,point d){//不相交时是否相遇
ld dx=d.x,dy=d.y;
if(abs(dx)<eps&&abs(dy)<eps)return 0;//d为0
for(int i=0;i<3;++i){
ld x=u.p[i].x,y=u.p[i].y;
for(int j=0;j<3;++j){
for(int q=j+1;q<3;++q){
ld k,b,t;
if(v.p[j].x!=v.p[q].x){//线段存在斜率
k=1.0*(v.p[j].y-v.p[q].y)/(v.p[j].x-v.p[q].x);
b=1.0*v.p[j].y-k*v.p[j].x;
if(abs(k*dx-dy)<eps){//d和线段平行
if(abs(dx)>eps){
t=1.0*(v.p[j].x-x)/dx;
if(t>=0&&OnSeg(point(x+t*dx,y+t*dy),line(v.p[j],v.p[q])))return 1;
}else{
t=1.0*(v.p[j].y-y)/dy;
if(t>=0&&OnSeg(point(x+t*dx,y+t*dy),line(v.p[j],v.p[q])))return 1;
}
}else{//d和线段不平行
t=1.0*(y-k*x-b)/(k*dx-dy);
if(t>=0&&OnSeg(point(x+t*dx,y+t*dy),line(v.p[j],v.p[q])))return 1;
}
}else if(dx!=0){//d不垂直与x轴
t=1.0*(v.p[j].x-x)/dx;
if(t>=0&&OnSeg(point(x+t*dx,y+t*dy),line(v.p[j],v.p[q])))return 1;
}else if(dx==0){//d垂直x轴
t=1.0*(v.p[j].y-y)/dy;
if(t>=0&&OnSeg(point(x+t*dx,y+t*dy),line(v.p[j],v.p[q])))return 1;
}
}
}
}
return 0;
}
bool check(san s,san t){
for(int i=0;i<3;++i){
for(int j=i+1;j<3;++j){
for(int x=0;x<3;++x){
for(int y=x+1;y<3;++y){
if(inter(line(s.p[i],s.p[j]),line(t.p[x],t.p[y]))==1)
return 1;
}
}
}
}
return 0;
}
int main(void){
scanf("%d",&T);
for(int tm=1;tm<=T;++tm){
for(int i=0;i<3;++i){
scanf("%d%d",&x,&y);
s.p[i]=point((ld)x,(ld)y);
}
scanf("%d%d",&x,&y);
sd=point((ld)x,(ld)y);
for(int i=0;i<3;++i){
scanf("%d%d",&x,&y);
t.p[i]=point((ld)x,(ld)y);
}
scanf("%d%d",&x,&y);
td=point((ld)x,(ld)y);
bool flag=check(s,t);//判断是否相交
if(!flag)flag=solve(s,t,sd-td)||solve(t,s,td-sd);
if(flag)printf("Case #%d: YES\n",tm);
else printf("Case #%d: NO\n",tm);
}
}
C
签到
#include <iostream>
using namespace std;
typedef long long ll;
const int N=1000+5;
ll T,n,b,c[N],d[N];
int main(void){
cin>>T;
while(T--){
cin>>n>>b;
for(int i=0;i<n;++i)
cin>>c[i];
for(int i=1;i<n;++i)
cin>>d[i];
bool flag=1;
ll cnt=0;
for(int i=0;i<n;++i){
cnt-=d[i];
if(cnt<0){
flag=0;
break;
}
cnt+=c[i];
}
if(flag)cout<<"Yes\n";
else cout<<"No\n";
}
}
D
dp
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=1000+5;
const ll inf=1e15;
ll c,h,b,dp[N][N][2];
struct node{
ll p,t;
friend bool operator<(node a,node b){
return a.p<b.p;
}
}a[N];
ll Abs(ll x){return x>0?x:-x;}
ll Max(ll x,ll y){return x>y?x:y;}
ll Min(ll x,ll y){return x<y?x:y;}
ll solve(ll l,ll r,ll op){
if(l<0||r>=c)return inf;
if(dp[l][r][op]!=-1)return dp[l][r][op];
if(op==0){
dp[l][r][op]=Min(Max(solve(l-1,r,0)+Abs(a[l-1].p-a[l].p),a[l].t),Max(solve(l,r+1,1)+Abs(a[r+1].p-a[l].p),a[l].t));
}else{
dp[l][r][op]=Min(Max(solve(l-1,r,0)+Abs(a[l-1].p-a[r].p),a[r].t),Max(solve(l,r+1,1)+Abs(a[r+1].p-a[r].p),a[r].t));
}
return dp[l][r][op];
}
int main(void){
scanf("%lld%lld%lld",&c,&h,&b);
for(int i=0;i<c;++i)scanf("%lld%lld",&a[i].p,&a[i].t);
sort(a,a+c);
memset(dp,-1,sizeof(dp));
dp[0][c-1][0]=Max(a[0].p,a[0].t);
dp[0][c-1][1]=Max(a[c-1].p,a[c-1].t);
ll ans=inf;
for(int i=0;i<c;++i)
ans=Min(ans,solve(i,i,0)+Abs(a[i].p-b));
printf("%lld\n",ans);
}
E
打表找规律
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a[]=
{
1LL,
8LL,
49LL,
288LL,
1681LL,
9800LL,
57121LL,
332928LL,
1940449LL,
11309768LL,
65918161LL,
384199200LL,
2239277041LL,
13051463048LL,
76069501249LL,
443365544448LL,
2584123765441LL,
15061377048200LL,
87784138523761LL,
511643454094368LL,
2982076586042449LL,
17380816062160328LL
};
int main()
{
int T,kase=1;
scanf("%d",&T);
while(T--)
{
ll n;
scanf("%lld",&n);
printf("Case #%d: %lld\n",kase++,*lower_bound(a,a+22,n));
}
return 0;
}
F
强连通分量
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+7;
vector<int> adj[N];
int low[N],dfn[N],st[N],id[N],top,tot,ins[N],col,ind[N],oud[N];
void tarjan(int u)
{
int v;
low[u]=dfn[u]=++tot;
st[top++]=u;
ins[u]=true;
for(int i=0;i<adj[u].size();++i)
{
int v=adj[u][i];
if(!dfn[v])
{
tarjan(v);
if(low[u]>low[v]) low[u]=low[v];
}
else if(ins[v]&&low[u]>dfn[v])
low[u]=dfn[v];
}
if(low[u]==dfn[u])
{
++col;
int v;
do
{
v=st[--top];
ins[v]=false;
id[v]=col;
}while(v!=u);
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i) adj[i].clear();
top=col=tot=0;
memset(ins,0,sizeof(ins));
memset(dfn,0,sizeof(dfn));
memset(ind,0,sizeof(ind));
memset(oud,0,sizeof(oud));
for(int i=0;i<m;++i)
{
int u,v;
scanf("%d%d",&u,&v);
adj[u].push_back(v);
}
for(int i=1;i<=n;++i)
if(!dfn[i]) tarjan(i);
for(int u=1;u<=n;++u)
{
for(int v : adj[u])
{
if(id[u]!=id[v])
++ind[id[v]],++oud[id[u]];
}
}
int n1=0,n2=0,n3=0;
for(int i=1;i<=col;++i)
{
if(ind[i]==0&&oud[i]==0) ++n3;
else if(ind[i]==0) ++n1;
else if(oud[i]==0) ++n2;
}
if(col==1) puts("0");
else printf("%d\n",n3-1+max(n1+1,n2+1));
}
return 0;
}
G
KMP+树状数组。复杂度 O(Tnlogn) 。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+7;
int c[N],nxt[N],n,m,ok[N];
char S[N],T[15];
int lowbit(int x)
{
return x&-x;
}
void update(int x,int k)
{
for(;x<=n;x+=lowbit(x))
c[x]+=k;
}
int query(int x)
{
int res=0;
for(;x>0;x-=lowbit(x))
res+=c[x];
return res;
}
void getNext(char s[],int n,int nxt[])
{
int i,j;
j=nxt[0]=-1;
i=0;
while(i<n)
{
while(-1!=j&&s[i]!=s[j]) j=nxt[j];
if(s[++i]==s[++j]) nxt[i]=nxt[j];
else nxt[i]=j;
}
}
void pre()
{
int i=0,j=0;
while(i<n)
{
while(-1!=j&&S[i]!=T[j]) j=nxt[j];
++i;++j;
if(j>=m)
{
update(i,ok[i]=1);
j=nxt[j];
}
}
}
void kmp(int p)
{
int i=max(p-m+1,0),j=0;
int L=min(p+m,n);
while(i<L)
{
while(-1!=j&&S[i]!=T[j]) j=nxt[j];
++i;++j;
if(j>=m)
{
if(!ok[i]) update(i,ok[i]=1);
j=nxt[j];
}
else if(ok[i]&&i-1>=p) update(i,-1),ok[i]=0;
}
}
int main()
{
int kase;
scanf("%d",&kase);
while(kase--)
{
int q;
scanf("%d",&q);
scanf("%s",S);
scanf("%s",T);
n=strlen(S);
m=strlen(T);
for(int i=1;i<=n;++i) ok[i]=c[i]=0;
getNext(T,m,nxt);
pre();
char op[5];
int l,r;
while(q--)
{
scanf("%s",op);
if(op[0]=='Q')
{
scanf("%d%d",&l,&r);
int ans;
if(r-l+1<m) ans=0;
else ans=query(r)-query(l+m-2);
printf("%d\n",ans);
}
else
{
scanf("%d %s",&l,op);
S[l-1]=op[0];
kmp(l-1);
}
}
puts("");
}
return 0;
}
H
dp
#include <cstdio>
#include <vector>
#include <queue>
#include <iostream>
#include <cstring>
using namespace std;
typedef long long ll;
const ll INF=1e15;
const int N=10000+5;
ll T,n,m,dp[N];
struct Edge{
ll v,cost;
Edge(ll _v=0,ll _cost=0):v(_v),cost(_cost){}
};
vector<Edge>E[N];
void init(){
memset(dp,-1,sizeof(dp));
for(int i=0;i<N;++i)
E[i].clear();
}
void addedge(ll u,ll v,ll w){
E[u].push_back(Edge(v,w));
}
ll solve(ll u){
if(dp[u]!=-1)return dp[u];
dp[u]=0;
for(int i=0;i<(int)E[u].size();++i){
ll v=E[u][i].v,c=E[u][i].cost;
dp[u]=max(dp[u],c+solve(v));
}
return dp[u];
}
int main(void){
scanf("%lld",T);
while(T--){
init();
scanf("%lld%lld",&n,&m);
for(int i=0;i<m;++i){
ll s,t,l;
scanf("%lld%lld%lld",&s,&t,&l);
if(s>t)addedge(s,t,l);
else if(t>s)addedge(t,s,l);
}
ll ans=0;
for(int i=1;i<=n;++i)
ans=max(ans,solve(i));
printf("%lld\n",ans);
}
}