151020 顺便ak祝自己生日快乐

T1

找规律大法好

发现数组单调就可以啦,写了个暴力验证了400组没问题 100

T2

倍增判断一个点是不是另外一个点的父亲

注意特判特殊情况 100

T3

暴力floyd n^4

spfa看似n^3然而事实上跑得比floyd还慢

dij n^3 log被卡成狗

bellman更是被卡成狗

然后我把我会的最短路全部写上去,最快65s完成n=500

然而题目只有三秒,然后开始各种黑科技最后12s(没有用啊)

想了好久,发现floyd好像可以优化一下

我们加入一个点,会出现3种情况

1.这个点作为中转点

2.这个点作为出点

3.这个点作为入点

如果单独处理这三种情况,可以少一个n

然后就愉快的写啦,过样例过不了对拍

还有3分钟交卷,愉快的写了个拼程序突然发现循环好像顺序不对

然后极限改过来,对拍3组交上去A掉了 100

附上代码

T1

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<iostream>
#include<algorithm>
#define in(a) for(int i=1;i<=n;i++)scanf("%I64d",&a[i]);
#define ll long long
ll n,a[100010],b[100010],x,y;
int main()
{
	freopen("math.in","r",stdin);
	freopen("math.out","w",stdout);
	scanf("%I64d",&n);
	in(a);in(b);
	std::sort(a+1,a+n+1);std::sort(b+1,b+n+1);
	for(int i=1;i<=n;i++)x+=a[i]*b[i],y+=a[i]*b[n-i+1];
	std::cout<<x<<" "<<y<<std::endl;
}
T2

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
inline void R(int &v)
{
	v=0;char c=0;int p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
struct Edge
{
	int to,len,next;
}edge[100010];
int deep[100010];
int first[100010],size;
int jump[100010][20];
int n,root,que[100010];
void addedge(int x,int y)
{
	size++;
	edge[size].to=y;
	edge[size].next=first[x];
	first[x]=size;
}
int main()
{
	freopen("tree.in","r",stdin);
	freopen("tree.out","w",stdout);
	R(n);
	for(int x,y,i=1;i<=n;i++)
	{
		R(x),R(y);
		if(y==-1)root=x;
		else addedge(x,y),addedge(y,x);
	}
	que[1]=root;
	for(int head=0,tail=1;head!=tail;)
	{
		head++;int v=que[head];deep[v]=deep[jump[v][0]]+1;
		for(int i=1;i<=18;i++)jump[v][i]=jump[jump[v][i-1]][i-1];
		for(int u=first[v];u;u=edge[u].next)
		{
			if(deep[edge[u].to])continue;
			jump[edge[u].to][0]=v;
			que[++tail]=edge[u].to;
		}
	}
	int q;R(q);
	while(q--)
	{
		int x,y;R(x),R(y);bool flag=false;
		if(x==y){puts("0");continue;}
		if(deep[x]<deep[y])x^=y^=x^=y,flag=true;
		int dep=deep[x]-deep[y];
		for(int i=18;i>=0;i--)
		{
			if((1<<i)<=dep)
			{
				dep-=(1<<i);
				x=jump[x][i];
			}
		}
		if(x==y)puts(flag?"1":"2");
		else puts("0");
	}
}
T3

1.floyd TLE

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#define inf 1000000000
#define rep(i) for(int i=1;i<=n;i++)
using namespace std;
inline void R(int &v)
{
	v=0;char c=0;int p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
int map[505][505];
int g[505][505];
int a[505];
bool p[505];
int n;
int query()
{
	int ret=0;
	rep(i)rep(j)
	{
		if(i==j)g[i][j]=0;
		else if(p[i] || p[j])g[i][j]=inf;
		else g[i][j]=map[i][j];
	}
	rep(i)rep(j)rep(k)if(g[j][k]>g[j][i]+g[i][k])g[j][k]=g[j][i]+g[i][k];
	rep(i)rep(j)
	{
		if(i==j)continue;
		else if(p[i] || p[j])continue;
		else ret+=g[i][j];
	}
	return ret;
}
int main()
{
	freopen("shortest.in","r",stdin);
	freopen("shortest.out","w",stdout);
	R(n);
	rep(i)rep(j)R(map[i][j]);
	rep(i)R(a[i]);
	rep(i)printf("%d ",query()),p[a[i]]=true;
}


2.spfa 跑得比floyd还慢!!

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#define inf 1000000000
#define rep(i) for(int i=1;i<=n;i++)
#define ll long long
using namespace std;
inline void R(int &v)
{
	v=0;char c=0;int p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
int map[505][505];
int a[505];
bool p[505];
int que[500005];
int n;
int dis[501];
bool exsit[501];
struct Edge
{
	int to,len,next;
}edge[500050];
int first[505],size;
void addedge(int x,int y,int z)
{
	size++;
	edge[size].to=y;
	edge[size].len=z;
	edge[size].next=first[x];
	first[x]=size;
}
ll spfa(int sta)
{
	memset(dis,63,sizeof dis);
	que[1]=sta;dis[sta]=0;
	for(int head=0,tail=1;head!=tail;)
	{
		exsit[que[++head]]=false;
		for(int u=first[que[head]];u;u=edge[u].next)
		{
			if((!p[edge[u].to]) && dis[edge[u].to]>dis[que[head]]+edge[u].len)
			{
				dis[edge[u].to]=dis[que[head]]+edge[u].len;
				if(!exsit[edge[u].to])que[++tail]=edge[u].to,exsit[edge[u].to]^=1;
			}
		}
	}
	ll ret=0;
	for(int i=1;i<=n;i++)if(!p[i])ret+=(ll)dis[i];
	return ret;
}
ll query()
{
	ll ret=0;
	rep(i)if(!p[i])ret+=spfa(i);
	return ret;
}
int main()
{
	freopen("shortest.in","r",stdin);
	freopen("shortest.out","w",stdout);
	R(n);
	rep(i)rep(j)R(map[i][j]);
	rep(i)rep(j)
	{
		if(i==j)continue;
		addedge(i,j,map[i][j]);
	}
	rep(i)R(a[i]);
	rep(i)printf("%I64d ",query()),p[a[i]]=true;
}
3.dij+heap 裸的dij更慢就不贴了

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<ext/pb_ds/priority_queue.hpp>
#define ll long long
#define inf 1000000000
#define rep(i) for(int i=1;i<=n;i++)
using namespace std;
typedef __gnu_pbds::priority_queue< pair<int,int> > heap;

inline void R(int &v)
{
	v=0;char c=0;int p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
struct Edge
{
	int to,len,next;
}edge[500050];
int first[505],size;
void addedge(int x,int y,int z)
{
	//fprintf(stderr,"%d %d %d\n",x,y,z);
	size++;
	edge[size].to=y;
	edge[size].len=z;
	edge[size].next=first[x];
	first[x]=size;
}
int n;
int map[505][505];
ll ans[505];
bool p[505];
bool used[505];
int dis[505];
int a[505];
int main()
{
	freopen("shortest.in","r",stdin);
	freopen("shortest.out","w",stdout);
	R(n);
	rep(i)rep(j)R(map[i][j]);
	rep(i)R(a[i]);
	for(int i=n;i>=1;i--)
	{
		for(int j=1;j<=n;j++)
		{
			if(!p[j])continue;
			addedge(j,a[i],map[j][a[i]]);
			addedge(a[i],j,map[a[i]][j]);
		}
		p[a[i]]=true;
		for(int j=1;j<=n;j++)
		{
			if(!p[j])continue;
			heap que;
			memset(used,false,sizeof used);
			memset(dis,63,sizeof dis);
			que.push(make_pair(0,j));dis[j]=0;
			for(int T=1;T<=n;T++)
			{
				if(que.empty())break;
				int x=que.top().second;que.pop();
				used[x]=true;
				for(int u=first[x];u;u=edge[u].next)
				{
					if(dis[edge[u].to]>dis[x]+edge[u].len)
					{
						dis[edge[u].to]=dis[x]+edge[u].len;
						if(!used[edge[u].to])
						{
							que.push(make_pair(-dis[edge[u].to],edge[u].to));
						}
					}
				}
			}
			for(int o=1;o<=n;o++)if(p[o])ans[i]+=(ll)dis[o];
		}
	}
	for(int i=1;i<=n;i++)
	{
		printf("%I64d ",ans[i]);
	}
}
4.正解

//Copyright(c)2015 liuchenrui
#include<cstdio>
#include<ctime>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
#define inf 1000000000
#define rep(i) for(int i=1;i<=n;i++)
using namespace std;
inline void R(int &v)
{
	v=0;char c=0;int p=1;
	while(c<'0' || c>'9'){if(c=='-')p=-1;c=getchar();}
	while(c>='0' && c<='9'){v=(v<<3)+(v<<1)+c-'0';c=getchar();}
	v*=p;
}
int map[505][505];
int g[505][505];
ll ans[505];
bool p[505];
int a[505];
int n;
int query()
{
	int ret=0;
	rep(i)rep(j)
	{
		if(i==j)g[i][j]=0;
		else if(p[i] || p[j])g[i][j]=inf;
		else g[i][j]=map[i][j];
	}
	rep(i)rep(j)rep(k)if(g[j][k]>g[j][i]+g[i][k])g[j][k]=g[j][i]+g[i][k];
	rep(i)rep(j)
	{
		if(i==j)continue;
		else if(p[i] || p[j])continue;
		else ret+=g[i][j];
	}
	return ret;
}
void Main()
{
	rep(i)rep(j)R(map[i][j]);
	rep(i)R(a[i]);
	rep(i)printf("%d ",query()),p[a[i]]=true;
	exit(0);
}
int main()
{
	freopen("shortest.in","r",stdin);
	freopen("shortest.out","w",stdout);
	R(n);
	if(n<=10)Main();
	rep(i)rep(j)R(map[i][j]);
	rep(i)R(a[i]);
	memset(g,63,sizeof g);
	for(int t=n;t>=1;t--)
	{
		int x=a[t];p[x]=true;
		rep(i)
		{
			if(i!=x && p[i])g[x][i]=map[x][i],g[i][x]=map[i][x];
		}
		ans[t]=ans[t+1];
		rep(i)rep(j)
		{
			if(i==x || j==x || i==j)continue;
			if((!p[i]) || (!p[j]))continue;
			if(g[j][x]>g[j][i]+g[i][x])g[j][x]=g[j][i]+g[i][x];
		}
		rep(i)rep(j)
		{
			if(i==x || j==x || i==j)continue;
			if((!p[i]) || (!p[j]))continue;
			if(g[x][j]>g[x][i]+g[i][j])g[x][j]=g[x][i]+g[i][j];
		}
		rep(i)rep(j)
		{
			if(i==x || j==x || i==j)continue;
			if((!p[i]) || (!p[j]))continue;
			if(g[i][j]>g[i][x]+g[x][j])
			{
				ans[t]-=(ll)(g[i][j]-g[i][x]-g[x][j]);
				g[i][j]=g[i][x]+g[x][j];
			}
		}
		
		rep(i)if(p[i] && i!=x)ans[t]+=(ll)(g[x][i]+g[i][x]);
	}
	for(int i=1;i<=n;i++)printf("%I64d ",ans[i]);
}






评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值