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