题解:
\(O(N^2)\)的暴力非常好拿,一种方便的方法是直接按要求连边然后\(SPFA\)飞快;
正解考虑动态规划:设状态为\(F[R]\),右端点为R的最大权值,转移为\(F[R]=max{F[close(L)]+W[i]}\),按右端点排序后直接二分出\(L\)的位置,同时可以用线段树维护前驱;
\(code\):
#include<cstdio>
#include<iostream>
#include<ctype.h>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<deque>
#include<algorithm>
#define reint register int
#define ll long long
#define ld double
#define l(x) (x<<1)
#define r(x) (x<<1|1)
#define rell register ll
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=(x<<1)+(x<<3)+(tt^'0');
if(flag) x=-x;
}
const int maxn=1e5+2;
struct point{
int x,y;
ll len;
inline point(int a=0,int b=0,int c=0)
{x=a,y=b,len=c;}
inline bool operator<(point a)const
{return y<a.y;}
}a[maxn];
int n;
ll f[maxn];
int main()
{
read(n);
for(int i=1;i<=n;i++)
{
int x,y;
ll z;
read(x),read(y),read(z);
a[i]=point(x,y,z);
}
sort(a+1,a+1+n);
for(int i=1;i<=n;i++)
{
f[i]=max(f[i-1],a[i].len);
int l=0,r=i-1,tmp=0;
while(l<=r)
{
int mid=l+r>>1;
if(a[mid].y<a[i].x) tmp=mid,l=mid+1;
else r=mid-1;
}
f[i]=max(f[i],f[tmp]+a[i].len);
}
printf("%lld",f[n]);
}
题解:
\(meet-in-the-middle\)搜索将指数折半时间复杂度\(O(2^{\frac{N}{2}}logN)\);
\(code:\)
#include<cstdio>
#include<iostream>
#include<ctype.h>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<deque>
#include<algorithm>
#define reint register int
#define ll long long
#define ld double
#define l(x) (x<<1)
#define r(x) (x<<1|1)
#define rell register ll
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=(x<<1)+(x<<3)+(tt^'0');
if(flag) x=-x;
}
const int maxn=42;
int n;
ll m,a[maxn];
int lowbit(int x){return x&-x;}
ll f[1<<20];
int cnt[1<<20];
void solve1()
{
for(int i=1;i<=n;i++) read(a[i]),cnt[1<<i-1]=i;
int tot=(1<<n)-1;
ll ans=1;
for(int i=1;i<=tot;i++)
{
f[i]=a[cnt[lowbit(i)]]+f[i^lowbit(i)];
if(f[i]<=m) ans++;
}
printf("%lld",ans);
}
ll g[1002];
void solve2()
{
ll ans=0;
for(int i=1;i<=n;i++) read(a[i]);g[0]=1;
for(int i=1;i<=n;i++)
for(int j=m;j>=a[i];j--)
g[j]=g[j]+g[j-a[i]];
for(int i=0;i<=m;i++)ans+=g[i];
printf("%lld",ans);
}
ll sum,ans,mid;
ll mx[1<<21],tot;
void dfs1(int x)
{
if(x==mid+1)
{
mx[++tot]=sum;
return;
}
dfs1(x+1);
if(sum+a[x]<=m)
{
sum+=a[x];
dfs1(x+1);
sum-=a[x];
}
}
void dfs2(int x)
{
if(x==n+1)
{
ans+=upper_bound(mx+1,mx+1+tot,m-sum)-mx-1;
return;
}
dfs2(x+1);
if(sum+a[x]<=m)
{
sum+=a[x];
dfs2(x+1);
sum-=a[x];
}
}
void solve()
{
for(int i=1;i<=n;i++) read(a[i]);
mid=n>>1;
dfs1(1);
sort(mx+1,mx+1+tot);
dfs2(mid+1);
printf("%lld",ans);
}
int main()
{
read(n),read(m);
if(n<=20) solve1();
else if(m<=1000) solve2();
else solve();
}
题解:
贪心,尽量限制对手的走法,统计\(2-(N-1)\)到\(1\)号\(N\)号点的距离,哪边近哪边先手;
\(code:\)
#include<cstdio>
#include<iostream>
#include<ctype.h>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<deque>
#include<algorithm>
#define reint register int
#define ll long long
#define ld double
#define l(x) (x<<1)
#define r(x) (x<<1|1)
#define rell register ll
using namespace std;
char buf[1<<20],*p1,*p2;
inline char gc()
{
// return getchar();
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}
template<typename T>
inline void read(T &x)
{
char tt;
bool flag=0;
while(!isdigit(tt=gc())&&tt!='-');
tt=='-'?(flag=1,x=0):(x=tt-'0');
while(isdigit(tt=gc())) x=(x<<1)+(x<<3)+(tt^'0');
if(flag) x=-x;
}
const int maxn=1e5+2;
int n,t,fa[maxn][20],log_[maxn],dep[maxn];
vector<int>G[maxn];
void dfs(int x,int pre)
{
fa[x][0]=pre;dep[x]=dep[pre]+1;
for(int i=1;i<=log_[n];i++)
if(fa[x][i-1]) fa[x][i]=fa[fa[x][i-1]][i-1];
else break;
for(auto it:G[x])
{
if(it==pre) continue;
dfs(it,x);
}
}
int getlca(int x,int y)
{
if(x==y) return x;
if(dep[x]<dep[y]) swap(x,y);
int del=dep[x]-dep[y];
for(int i=log_[n];i>=0;i--)
if(del>>i&1) x=fa[x][i];
if(x==y) return x;
for(int i=log_[n];i>=0;i--)
if(fa[x][i]!=fa[y][i])
x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
int cal(int x,int y)
{return dep[x]+dep[y]-(dep[getlca(x,y)]<<1);}
int main()
{
read(t);
log_[0]=-1;
for(int i=1;i<=maxn-1;i++) log_[i]=log_[i>>1]+1;
while(t--)
{
read(n);
memset(dep,0,sizeof(dep));
memset(fa,0,sizeof(fa));
for(int i=1;i<=n;i++) G[i].clear();
for(int i=1;i<n;i++)
{
int x,y;
read(x),read(y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs(1,0);
ll ans0=0,ans1=0;
for(int i=2;i<n;i++)
{
int t1=cal(1,i);
int t2=cal(n,i);
if(t1<=t2) ans0++;
else ans1++;
}
if(ans0>ans1) puts("^_^");
else puts("T_T");
}
}