20 条题解
-
7
Bill_Yang LV 10 @ 7 年前
此题可以使用链表/平衡树+倍增的方法A掉
先讲讲暴力
暴力(70分):
暴力预处理每个点可以到达的最短和次短的位置O(n^2)
然后暴力枚举每个点模拟
代码如下:接下来讲讲正解:
我们要优化这份代码,必须着手于两个O(n^2)第一个:预处理最短和次短。
我们可以按照权值建一个双向链表,然后快速O(n)维护出每个权值的前驱后继,进而就可以得出最短和次短。
或者也可以使用平衡树等数据结构O(nlogn)维护出前驱后继,虽然可以过,但是常数可想而知。第二个:模拟
我们一个一个走模拟到最终位置,这样太慢了,怎么办呢?
走的过程已经定下来了,有没有快速的方法求出其终点?
使用倍增,就像爬树快速找到LCA一样,我们预处理后可以快速获得其最终位置。
如何倍增?
将A走一步和B走一步和在一起,变为AB一起分别走一步,那么接下来每一个周期都是定的,就可以倍增走了,边倍增边维护路径上的总和,进而可以处理掉x的限制。代码如下:
还有注意ans[1]别开太大,否则可能会乘爆,开1e10即可。
-
27 年前@
-
16 年前@
用双向链表+倍增方法AC(具体可以开其他大佬的题解,这里不详细描述)
下面是有良心带注释的代码a.a -
17 年前@
-
17 年前@
贡献一个用
set
实现的预处理,清晰易懂。 -
08 年前@
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const int M = 100005;
const double INF = 0x7fffffff;
typedef long long LL;struct City{
int h, id;
City *r, *l;
City(int a=0, int b=0):h(a), id(b){}
bool operator < (const City& x) const{
return h < x.h;
}
}c[M], bri[6];bool cmp(City a, City b){
if(abs(a.h) == abs(b.h))
return a.h < b.h;
return abs(a.h) < abs(b.h);
}int n;
int f[M][20], pos[M], to[M], to2[M], f_b[M], h[M];
LL fa[M][20], fb[M][20];void add(City& a, City& b){
b.r = a.r;
a.r = &b;
b.l = &a;
}void delet(City& x){
if(x.r != NULL) x.r->l = x.l;
if(x.l != NULL) x.l->r = x.r;
}void init(){
sort(c+1, c+1+n);
c[1].l = c[1].r = NULL;
for(int i = 1; i < n; i++)
add(c[i], c[i+1]); //构建双向链表
for(int i = 1; i <= n; i++)
pos[c[i].id] = i; //pos[i]: i 在双向链表中的位置
for(int po = 1; po <= n; po++){ //从1到n找下一个位置,找完删除
int cnt = 0, i = pos[po];
//找海拔较低的
for(City* q = c[i].l; q != NULL && cnt < 2; q = q->l)
if(q->id > c[i].id)
bri[++cnt] = City(q->h - c[i].h, q->id);
//找海拔较高的
int lim = cnt + 1;
for(City* q = c[i].r; q != NULL && cnt <= lim; q = q->r)
if(q->id > c[i].id)
bri[++cnt] = City(q->h - c[i].h, q->id);
if(cnt >= 2) sort(bri+1, bri+1+cnt, cmp);//排序
if(cnt >= 2) fa[po][0] = abs(bri[2].h), to2[po] = bri[2].id;//倍增
if(cnt >= 1) fb[po][0] = abs(bri[1].h), to[po] = bri[1].id;
delet(c[i]);//delet po
}
for(int i = 1; i <= n; i++) f_b[i] = fb[i][0];
for(int i = 1; i <= n; i++){
f[i][0] = to[to2[i]];
fb[i][0] = f_b[to2[i]];
}
for(int j = 1; j <= 19; j++)//倍增
for(int i = 1; i <= n; i++){
f[i][j] = f[f[i][j-1]][j-1];//f记录a走的下一个地点,因为a先走,可能多走一步
fa[i][j] = fa[i][j-1] + fa[f[i][j-1]][j-1];
fb[i][j] = fb[i][j-1] + fb[f[i][j-1]][j-1];
}
}void solve(){
int x0, ans = 1;
scanf("%d", &x0);
long double mins = INF;
for(int i = 1; i <= n; i++){
int x = i;
LL t1 = 0, t2 = 0;
double res = 0;
for(int j = 19; j >= 0; j--)
if(f[x][j] && t1 + t2 + fa[x][j] + fb[x][j] <= x0){
t1 += fa[x][j];
t2 += fb[x][j];
x = f[x][j];
}
if(t1 + t2 + fa[x][0] <= x0) t1 += fa[x][0];
if(t2 == 0) res = INF;
else res = (double)t1 / (double)t2;
if(res < mins || (res == mins && h[ans] < h[i])){
mins = res;
ans = i;
}
}
printf("%d\n", ans);
}void clac(int s, int x){
LL t1 = 0, t2 = 0;
for(int j = 19; j >= 0; j--)
if(f[s][j] && t1 + t2 + fa[s][j] + fb[s][j] <= x){
t1 += fa[s][j];
t2 += fb[s][j];
s = f[s][j];
}
if(t1 + t2 + fa[s][0] <= x) t1 += fa[s][0];
printf("%lld %lld\n", t1, t2);
}void solve2(){
int m;
scanf("%d", &m);
for(int i = 1; i <= m; i++){
int s, x;
scanf("%d%d", &s, &x);
clac(s, x);
}
}int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++){
scanf("%d", &c[i].h);
h[i] = c[i].h, c[i].id = i;
}
init();
solve();
solve2();
return 0;
}
链表 + 倍增 -
08 年前@
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <set>
#include <cmath>
using namespace std;
const int maxn = 200000+10;
typedef long long LL;
//next1,next2表示i位置的第一近的位置号和第二位置号
int g[maxn][20+2],next1[maxn],next2[maxn];
LL len1[maxn],len2[maxn]; //表示位置i第一近和第二近的路程
LL lenA,lenB; //lenA表示A走的总路程 lenB表示B走的总路程
int n,m,i,j;
struct road
{
LL A,B;
//重载运算符+
road operator +(const road &a)
{
road c;
c.A = A + a.A;
c.B = B + a.B;
return c;
}
}f[maxn][20+2];
struct Point
{
int id, h; //位置号和高度值
//重载比较运算符
bool operator<(const Point &a) const
{
return h < a.h;
}
}p[maxn];
//定义多关键字集合
multiset<Point> S;
//定义多关键字集合的一个变量
multiset<Point>::iterator it;
//更新数组i的 next1 和 next2 与j的位置
void updata(int i ,int h,int j,int h2)
{
if (!next1[i])
{
next1[i] = j;
len1[i]= abs(h-h2);
return ;
}
if ((abs(h-h2) == len1[i] && p[next1[i]].h > h2)
|| (abs(h-h2) < len1[i]))
{
next2[i] = next1[i];
len2[i] = len1[i];next1[i] = j;
len1[i] = abs(h-h2);
return ;
}
if (!next2[i])
{
next2[i] = j;
len2[i]= abs(h-h2);
return ;
}
if ((abs(h-h2)== len2[i] && p[next1[i]].h > h2)
|| (abs(h-h2) < len2[i]))
{
next2[i]= j;
len2[i] = abs(h-h2);
}
}
//询问从st位置出发a和b走的总路程不超过len 存储的路程为lenA和lenB
void ask(int st,LL len)
{
for (int j = 20; j >=0; j--)
{
if (g[st][j]!=0 && f[st][j].A+f[st][j].B<=len)
{
len -= (f[st][j].A+f[st][j].B);
lenA+=f[st][j].A;
lenB+=f[st][j].B;
st = g[st][j];
}
}
if (next2[st] && len>=len2[st])
lenA +=len2[st];
}int main()
{
cin>>n;
for (int i = 1; i <= n; ++i)
{
scanf("%d", &p[i].h);
p[i].id = i;
}
for (int i = n; i>=1; --i)
{
//查找节点p[i]在升序中的位置
it = S.lower_bound(p[i]);
if (it != S.end()) //不是末尾
updata(i , p[i].h, it->id, it->h);if (it != S.end()) //不是末尾
{
it++; //访问后一个
if (it != S.end())
updata(i , p[i].h, it->id, it->h);
it--;
}if (it != S.begin())
{
it--;
updata(i , p[i].h, it->id, it->h);
}
if (it != S.begin())
{
it--;
updata(i , p[i].h, it->id, it->h);
}
S.insert(p[i]);
}for (int i = 1; i <= n;++i)
{
//倍增关系是A走2个位置B走一个位置
g[i][0] = next1[next2[i]];
f[i][0].A =len2[i];
f[i][0].B =len1[next2[i]];
}
for (int i = 1; i <= 20; ++i)
for (int j = 1; j <= n;++j)
{
//倍增
g[j][i] = g[g[j][i-1]][i-1];f[j][i]= f[j][i-1]+ f[g[j][i-1]][i-1];
}
LL x;
cin>>x;
LL ansA = (LL)round(10e9);
LL ansB = 0;
int Pos = 0;
//从i号出发 走的路程为x
for (int i = 1; i <= n;++i)
{lenA = lenB = 0;
ask(i,x);if (lenB != 0)
{
//存储lenA/lenB的比值最小
if (Pos ==0 || ansA*lenB > lenA * ansB)
{
Pos = i;
ansA = lenA;
ansB = lenB;
}
}
}
cout << Pos << endl;
cin>>m;
for (int i = 1; i <= m; ++i)
{
int st;
scanf("%d %d",&st,&x);
lenA = lenB = 0;
ask(st,x);
cout<<lenA<<" "<<lenB <<endl;
}
return 0;
} -
08 年前@
调了半个小时发现错因是我把城市从零开始编号但是输入输出的时候忘了转换。。。真的是哭都哭不出来了
-
09 年前@
测试数据 #0: WrongAnswer, time = 0 ms, mem = 28692 KiB, score = 0
测试数据 #1: WrongAnswer, time = 15 ms, mem = 28688 KiB, score = 0
测试数据 #2: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #3: WrongAnswer, time = 0 ms, mem = 28692 KiB, score = 0
测试数据 #4: WrongAnswer, time = 0 ms, mem = 28692 KiB, score = 0
测试数据 #5: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #6: WrongAnswer, time = 15 ms, mem = 28688 KiB, score = 0
测试数据 #7: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #8: WrongAnswer, time = 15 ms, mem = 28692 KiB, score = 0
测试数据 #9: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #10: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #11: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #12: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #13: WrongAnswer, time = 0 ms, mem = 28692 KiB, score = 0
测试数据 #14: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #15: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #16: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #17: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #18: WrongAnswer, time = 0 ms, mem = 28688 KiB, score = 0
测试数据 #19: WrongAnswer, time = 0 ms, mem = 28692 KiB, score = 0
WrongAnswer, time = 45 ms, mem = 28692 KiB, score = 0
这时间,这结果
-
09 年前@
预处理可以不用平衡树,排个序+双向链表就能搞定~
-
010 年前@
由于VJ的数据加强过,set会TLE。。。
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;const int Maxn=1e5+19;
typedef long long LL;
typedef int node[Maxn];
typedef pair<LL,int> PII;
typedef int Array[Maxn][21];
int n,m,x0,X,s,Ans;
int A[Maxn],Bnxt[Maxn];
double Dis=1e70,Hi;
Array Da,Db,to;int f,c;
inline void Read(int &x)
{
while (!isdigit(c=getchar())&&c!='-');
if (c=='-') f=1,x=0;else f=0,x=c-'0';
while (isdigit(c=getchar())) x=x*10+c-'0';
if (f) x=-x;
}int rt;
struct SBT
{
int cnt;
node Lsn,Rsn,s;
PII key[Maxn];inline void Update(int x) {s[x]=s[Lsn[x]]+s[Rsn[x]]+1;}
inline void R_Rot(int &x)
{
int k=Lsn[x];Lsn[x]=Rsn[k];Rsn[k]=x;
s[k]=s[x];Update(x);x=k;
}
inline void L_Rot(int &x)
{
int k=Rsn[x];Rsn[x]=Lsn[k];Lsn[k]=x;
s[k]=s[x];Update(x);x=k;
}
inline void Maintain(int &x,int Flag)
{
if (!Flag)
if (s[Lsn[Lsn[x]]]>s[Rsn[x]]) R_Rot(x);
else if (s[Rsn[Lsn[x]]]>s[Rsn[x]]) L_Rot(Lsn[x]),R_Rot(x);else return;
else if (s[Rsn[Rsn[x]]]>s[Lsn[x]]) L_Rot(x);
else if (s[Lsn[Rsn[x]]]>s[Lsn[x]]) R_Rot(Rsn[x]),L_Rot(x);else return;
Maintain(Lsn[x],0);Maintain(Rsn[x],1);
Maintain(x,1);Maintain(x,0);
}
inline void insert(int &x,PII v)
{
if (!x) {x=++cnt,key[x]=v,s[x]=1;return;}
s[x]++;
insert(v<key[x]?Lsn[x]:Rsn[x],v);
Maintain(x,v>=key[x]);
}
inline int find(PII v)
{
int x=rt;
while (1)
{
if (key[x]==v) return x;
x=(v<key[x]?Lsn[x]:Rsn[x]);
}
}
inline PII pre(int x,PII v)
{
if (!x) return v;
if (v<=key[x]) return pre(Lsn[x],v);
else {PII tmp=pre(Rsn[x],v);return tmp==v?key[x]:tmp;}
}
inline PII nxt(int x,PII v)
{
if (!x) return v;
if (v>=key[x]) return nxt(Rsn[x],v);
else {PII tmp=nxt(Lsn[x],v);return tmp==v?key[x]:tmp;}
}
} S;int main()
{
freopen("drive.in","r",stdin);
freopen("drive.out","w",stdout);
scanf("%d",&n);
for (int i=1;i<=n;i++) Read(A[i]);
S.insert(rt,make_pair(1LL<<60,0));
S.insert(rt,make_pair(-(1LL<<60),0));
for (int i=n;i>=1;i--)
{
PII x=make_pair(1LL*A[i],i);int k;
S.insert(rt,x);
PII L=S.pre(rt,x),R=S.nxt(rt,x),T;
if (i==n) continue;
if (i==n-1) {Bnxt[i]=n;continue;}
if (abs(L.first-A[i])<=abs(R.first-A[i]))
{
Bnxt[i]=L.second;T=S.pre(rt,L);
k=(abs(T.first-A[i])<=abs(R.first-A[i])?T.second:R.second);
} else
{
Bnxt[i]=R.second;T=S.nxt(rt,R);
k=(abs(L.first-A[i])<=abs(T.first-A[i])?L.second:T.second);
}
to[i][1]=Bnxt[k];
Da[i][1]=abs(A[k]-A[i]);
Db[i][1]=(k?abs(A[k]-A[Bnxt[k]]):0);
}
for (int x=2;x<=20;x++)
for (int i=1;i<=n;i++)
{
int p=to[i][x-1];
to[i][x]=to[p][x-1];
Da[i][x]=Da[i][x-1]+Da[p][x-1];
Db[i][x]=Db[i][x-1]+Db[p][x-1];
}
scanf("%d",&x0);
for (int y=1;y<=n;y++)
{
int s=y,X=x0,Aa=0,Ab=0;
for (int i=20;i>=1;i--)
if (to[s][i]&&Da[s][i]+Db[s][i]<=X)
{
Aa+=Da[s][i],Ab+=Db[s][i];
X-=Da[s][i]+Db[s][i];
s=to[s][i];
}
if (Da[s][1]<=X) Aa+=Da[s][1];
double x=(!Ab?1e60:(1.0*Aa)/(1.0*Ab));
if (x<Dis-1e-9||fabs(x-Dis)<1e-9&&A[y]>Hi) Dis=x,Hi=A[y],Ans=y;
}
printf("%d\n",Ans);
scanf("%d",&m);
while (m--)
{
Read(s),Read(X);
int Aa=0,Ab=0;
for (int i=20;i>=1;i--)
if (to[s][i]&&Da[s][i]+Db[s][i]<=X)
{
Aa+=Da[s][i],Ab+=Db[s][i];
X-=Da[s][i]+Db[s][i];
s=to[s][i];
}
if (Da[s][1]<=X) Aa+=Da[s][1];
printf("%d %d\n",Aa,Ab);
}
} -
010 年前@
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF=~0U>>2;
int n;
struct High
{
int ord,Val;
}R[100005];
int H[100005];
struct List
{
int Val,next,last;
}L[100005];
inline bool Cmp(const High& A,const High& B)
{
return A.Val<B.Val;
}
struct Tree
{
int S_A,S_B;
int C_A,C_B;
int S[18],CA[18],CB[18];
}T[100005];
inline void Build(int Pc,int Pr)
{
T[Pc].C_A=T[Pc].C_B=INF;
if (L[Pr].last)
if (H[Pc]-H[L[L[Pr].last].Val]<T[Pc].C_B)
T[Pc].S_B=L[L[Pr].last].Val,T[Pc].C_B=H[Pc]-H[L[L[Pr].last].Val];
if (L[Pr].next)
if (H[L[L[Pr].next].Val]-H[Pc]<T[Pc].C_B)
T[Pc].S_B=L[L[Pr].next].Val,T[Pc].C_B=H[L[L[Pr].next].Val]-H[Pc];
if (T[Pc].S_B)
{
if (L[Pr].last)
{
if (L[L[Pr].last].Val!=T[Pc].S_B)
T[Pc].S_A=L[L[Pr].last].Val,T[Pc].C_A=H[Pc]-H[L[L[Pr].last].Val];
if (L[L[Pr].last].last && L[L[Pr].last].Val==T[Pc].S_B)
T[Pc].S_A=L[L[L[Pr].last].last].Val,T[Pc].C_A=H[Pc]-H[T[Pc].S_A];
}
if (L[Pr].next)
{
if (L[L[Pr].next].Val!=T[Pc].S_B)
if (H[L[L[Pr].next].Val]-H[Pc]<T[Pc].C_A)
T[Pc].S_A=L[L[Pr].next].Val,T[Pc].C_A=H[L[L[Pr].next].Val]-H[Pc];
if (L[L[Pr].next].next && L[L[Pr].next].Val==T[Pc].S_B)
if (H[L[L[L[Pr].next].next].Val]-H[Pc]<T[Pc].C_A)
T[Pc].S_A=L[L[L[Pr].next].next].Val,T[Pc].C_A=H[L[L[L[Pr].next].next].Val]-H[Pc];
}
}
if (L[Pr].last) L[L[Pr].last].next=L[Pr].next;
if (L[Pr].next) L[L[Pr].next].last=L[Pr].last;
}
int Find(int x)
{
int l=1,r=n,mid;
while (l<r-1)
{
mid=(l+r)>>1;
if (R[mid].Val<x) l=mid;
else r=mid;
}
for (int i=l;i<=r;i++)
if (R[i].Val==x) return i;
}
void Double_Inc(int Ps)
{
T[Ps].S[0]=T[T[Ps].S_A].S_B;
T[Ps].CA[0]=T[Ps].C_A;
T[Ps].CB[0]=T[T[Ps].S_A].C_B;
for (int i=1;i<18;i++)
{
T[Ps].S[i]=T[T[Ps].S[i-1]].S[i-1];
T[Ps].CA[i]=T[Ps].CA[i-1]+T[T[Ps].S[i-1]].CA[i-1];
T[Ps].CB[i]=T[Ps].CB[i-1]+T[T[Ps].S[i-1]].CB[i-1];
}
}
pair<int,int> Get_Ans(int P,int x)
{
int D_A=0,D_B=0;
int V=17;
while (true)
{
while ((T[P].S[V]==0 || T[P].CA[V]+T[P].CB[V]>x) && V>=0) V--;
if (V>=0) D_A+=T[P].CA[V],D_B+=T[P].CB[V],x-=T[P].CA[V]+T[P].CB[V],P=T[P].S[V];
else break;
}
if (T[P].S_A && T[P].C_A<=x) D_A+=T[P].C_A;
return pair<int,int>(D_A,D_B);
}
inline double Calc(int A,int B)
{
if (B==0) return 1000000000.0;
return (double)A/B;
}
int main()
{
scanf("%d",&n);
for (int i=1;i<=n;i++) scanf("%d",H+i),R[i].Val=H[i],R[i].ord=i;
sort(R+1,R+n+1,Cmp);
for (int i=1;i<=n;i++) L[i].Val=R[i].ord;
for (int i=1;i<n;i++) L[i].next=i+1;
for (int i=2;i<=n;i++) L[i].last=i-1;
for (int i=1;i<=n;i++) Build(i,Find(H[i]));
for (int i=n;i;i--) Double_Inc(i);
int X0;
scanf("%d",&X0);
int ans;
double Cur=10000000000.0;
for (int i=n;i;i--)
{
pair<int,int> T=Get_Ans(R[i].ord,X0);
if (Calc(T.first,T.second)<Cur-1e-8) ans=R[i].ord,Cur=Calc(T.first,T.second);
}
printf("%d\n",ans);
int m;
scanf("%d",&m);
for (int i=1,p,x;i<=m;i++)
{
scanf("%d%d",&p,&x);
pair<int,int> T=Get_Ans(p,x);
printf("%d %d\n",T.first,T.second);
}
return 0;
} -
011 年前@
终于过了~~
编译成功foo.cpp: In function 'int WORK1()':
foo.cpp:269:1: warning: no return statement in function returning non-void [-Wreturn-type]
测试数据 #0: Accepted, time = 31 ms, mem = 49852 KiB, score = 5
测试数据 #1: Accepted, time = 31 ms, mem = 49856 KiB, score = 5
测试数据 #2: Accepted, time = 31 ms, mem = 49856 KiB, score = 5
测试数据 #3: Accepted, time = 31 ms, mem = 49860 KiB, score = 5
测试数据 #4: Accepted, time = 31 ms, mem = 49856 KiB, score = 5
测试数据 #5: Accepted, time = 31 ms, mem = 49856 KiB, score = 5
测试数据 #6: Accepted, time = 31 ms, mem = 49864 KiB, score = 5
测试数据 #7: Accepted, time = 31 ms, mem = 49864 KiB, score = 5
测试数据 #8: Accepted, time = 31 ms, mem = 49864 KiB, score = 5
测试数据 #9: Accepted, time = 31 ms, mem = 49864 KiB, score = 5
测试数据 #10: Accepted, time = 31 ms, mem = 49900 KiB, score = 5
测试数据 #11: Accepted, time = 46 ms, mem = 49900 KiB, score = 5
测试数据 #12: Accepted, time = 31 ms, mem = 49900 KiB, score = 5
测试数据 #13: Accepted, time = 46 ms, mem = 49892 KiB, score = 5
测试数据 #14: Accepted, time = 250 ms, mem = 52204 KiB, score = 5
测试数据 #15: Accepted, time = 312 ms, mem = 52204 KiB, score = 5
测试数据 #16: Accepted, time = 625 ms, mem = 53624 KiB, score = 5
测试数据 #17: Accepted, time = 609 ms, mem = 54088 KiB, score = 5
测试数据 #18: Accepted, time = 718 ms, mem = 54556 KiB, score = 5
测试数据 #19: Accepted, time = 687 ms, mem = 54552 KiB, score = 5
Accepted, time = 3665 ms, mem = 54556 KiB, score = 100
发一下题解:
http://hi.baidu.com/vporvgjwxchmpwe/item/651f91edf52a642d6cabb818 -
-18 年前@
其实很简单,不是很难的。
用一点数据结构,就解决了。 -
-18 年前@
#1
AC
1ms/9398kB#2
AC
1ms/9398kB#3
AC
2ms/9398kB#4
AC
1ms/106449kB#5
AC
2ms/9398kB#6
AC
1ms/9398kB#7
AC
1ms/9410kB
#8
AC
2ms/9406kB#9
AC
4ms/106449kB#10
AC
3ms/106449kB#11
AC
16ms/106449kB#12
AC
19ms/9480kB#13
AC
16ms/9492kB#14
AC
20ms/106449kB
#15
AC
163ms/108640kB#16
AC
171ms/35515kB#17
AC
435ms/110058kB#18
AC
442ms/110445kB#19
AC
517ms/110960kB#20
AC
546ms/110960kB -
-111 年前@
郁闷的wa了20分
测试数据 #0: Accepted, time = 0 ms, mem = 36836 KiB, score = 5
测试数据 #1: Accepted, time = 15 ms, mem = 36836 KiB, score = 5
测试数据 #2: Accepted, time = 0 ms, mem = 36836 KiB, score = 5
测试数据 #3: Accepted, time = 0 ms, mem = 36832 KiB, score = 5
测试数据 #4: WrongAnswer, time = 0 ms, mem = 36836 KiB, score = 0
测试数据 #5: Accepted, time = 0 ms, mem = 36832 KiB, score = 5
测试数据 #6: Accepted, time = 0 ms, mem = 36836 KiB, score = 5
测试数据 #7: Accepted, time = 15 ms, mem = 36832 KiB, score = 5
测试数据 #8: Accepted, time = 15 ms, mem = 36832 KiB, score = 5
测试数据 #9: Accepted, time = 0 ms, mem = 36832 KiB, score = 5
测试数据 #10: Accepted, time = 31 ms, mem = 36836 KiB, score = 5
测试数据 #11: Accepted, time = 31 ms, mem = 36832 KiB, score = 5
测试数据 #12: Accepted, time = 15 ms, mem = 36832 KiB, score = 5
测试数据 #13: Accepted, time = 31 ms, mem = 36836 KiB, score = 5
测试数据 #14: WrongAnswer, time = 187 ms, mem = 36832 KiB, score = 0
测试数据 #15: WrongAnswer, time = 234 ms, mem = 36832 KiB, score = 0
测试数据 #16: Accepted, time = 515 ms, mem = 36832 KiB, score = 5
测试数据 #17: WrongAnswer, time = 625 ms, mem = 36832 KiB, score = 0
测试数据 #18: Accepted, time = 625 ms, mem = 36832 KiB, score = 5
测试数据 #19: Accepted, time = 484 ms, mem = 36832 KiB, score = 5
WrongAnswer, time = 2823 ms, mem = 36836 KiB, score = 80 -
-111 年前@
由于这道题只过了NOIP的数据,VJ还是过不来,就只说说思路:
由于Hi各不相同,所以可以使用平衡树来预处理每个城市最近和第二近的城市,从东往西向平衡树中加入城市,在假如前顺便查询每个城市各自在两人开车的情况下到达的下一个城市。
第二步预处理:倍增算法
f[0][i][j]表示在A先开车的情况下从i出发,经过2^j步到达的城市
f[1][i][j]表示在A先开车的情况下从i出发,经过2^j步到达的城市
可得状态转移方程:
j=1
f[0][i][j]=f[1][f[0][i][j-1]][j-1];
f[1][i][j]=f[0][f[0][i][j-1]][j-1];
j>1
f[0][i][j]=f[0][f[0][i][j-1]][j-1];
f[1][i][j]=f[1][f[1][i][j-1]][j-1];
然后 要查询时递归查询即可
预处理复杂度O(n log n)
查询复杂度O(m log n) -
-211 年前@
Q_Q 木有题解
-
-212 年前@
SOFA
- 1