2018.10.31 练习赛

T1 【NOIP2018模拟】草地排水

题解:

\(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]);
}

【NOIP2018模拟】化学

题解:

\(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();
}

T3 【NOIP2018模拟】读书

题解:

贪心,尽量限制对手的走法,统计\(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");
	}
}
posted @ 2018-10-31 23:23  Katoumegumi  阅读(47)  评论(0编辑  收藏  举报
返回顶部