标签:oid game 优化 模拟 amp eve wap ++ 结束
丁国建造了 n 座激光塔。
“ 当若干座激光塔相连并形成环形线路,你就能获得上神的力量。”这是丁国国王从大魔王那得知的消息。
第二天,丁国国王便下令修建 \(m\) 条连接激光塔的线路。
你作为甲国派来的间谍,无意间听到了这个消息,当即决定破坏这场密谋。每座激光塔的坐标为\((x_i,y_i)\),正在修建的线路\((u_i,v_i)\)表示连接编号为 \(u_i\) 和 \(v_i\) 的激光塔,破坏该条线路的代价为两座激光塔的直线距离。求破坏这场密谋的最小代价。
第一行两个整数 \(n, m\)
接下来 \(n\) 行, 每行两个整数 \(x_i\), \(y_i\), 代表点 \(i\) 的坐标
接下来 \(m\) 行, 每行两个整数 \(u_i\), \(v_i\), 代表一条边 \((u_i, v_i)\)
输出一个实数代表答案, 当答案与标准答案之差的绝对值不超过 \(10^{-4}\) 时视为正确。
input1
3 3
0 0
0 1
1 0
1 2
2 3
1 3
output1
1.000000000
input2
8 8
0 0
3 0
3 3
0 3
1 1
1 2
2 2
2 1
1 2
2 3
3 4
4 1
5 6
6 7
7 8
8 5
output2
4.000000000
对于前 \(20\%\)的数据:\(n,m \leq 20\)
对于前 \(50\%\)的数据:\(n,m \leq 1 000\)
对于 \(100\%\) 的数据:\(1 \leq n \leq 10000\) , \(1 \leq m \leq 50000\) , \(|x_i|,|y_i| \leq 10000\) , \(u_i ! = v_i\),不存在两点重合的情况.
时间限制:1s
空间限制:512MB
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
const int N=1e4+10;
const int M=5e4+10;
int n,m,x[N],y[N],b[N];
double ans;
struct edge{int a,b;double c;}ed[M];
inline double dis(int a,int b){return sqrt(((double)x[a]-x[b])*((double)x[a]-x[b])+((double)y[a]-y[b])*((double)y[a]-y[b]));}
bool cmp(edge x,edge y){return x.c>y.c;}
inline int f(int x){if(b[x]!=x)b[x]=f(b[x]);return b[x];}
int main(){
freopen("plan.in","r",stdin);freopen("plan.out","w",stdout);
scanf("%d%d",&n,&m);
for(register int i=1;i<=n;i++)scanf("%d%d",&x[i],&y[i]);
for(register int i=1;i<=m;i++)scanf("%d%d",&ed[i].a,&ed[i].b),ed[i].c=dis(ed[i].a,ed[i].b);
sort(ed+1,ed+m+1,cmp);for(register int i=1;i<=n;i++)b[i]=i;
for(register int i=1;i<=m;i++){
int f1=f(ed[i].a),f2=f(ed[i].b);if(f1==f2){ans+=ed[i].c;continue;}b[f2]=f1;}
printf("%.9lf\n",ans);
fclose(stdin);fclose(stdout);
return 0;
}
丁国国王的密谋被破坏了。
大魔王很生气,并且他知道是你坏了他的好事,于是他找来你。
“跟我玩个游戏,你赢了,我就放你走。”
游戏是这样的:你和大魔王在一个规模为 \(1 * n\) 的棋盘中下棋,第一个人可以下在第\(1\) 到 \(m\) 中的任意一个位置。接下来每一个人可以下在第 \(i + 1\) 到 \(i + m\) 的任意一个位置,其中 \(i\) 为上一个人下棋的位置。每个格子里有一个数,如果一个人下棋在格子 \(i\),会得到 \(a[i]\)的分值。当不能继续操作时,游戏结束。
大魔王允许你编个程序计算一下,当你和大魔王都采取 最优策略时, 你的得分减去大魔王的得分。
你们决定通过掷硬币来决定先后手,因此你要把你先后手的两种情况都考虑一下。
第一行:两个正整数 \(n\) 和 \(m\) , 用空格隔开。
第二行:\(n\) 个数,表示棋盘上的数字。
两行,每行各一个数, 第一个数为你先手时的答案, 第二个数为你后手时的答案。
input1
1 3
1
output1
1
-1
input2
2 100
2 2
output2
2
-2
对于前 \(30\%\)的数据:\(n \leq 15\)
对于前 \(60\%\)的数据:\(m \leq 100\)
对于 \(100\%\) 的数据:\(1 \leq n,m \leq 100000\) ,a 数组中的数保证在 int 范围内。
时间限制:1s
空间限制:512MB
\[dp[i][0]=max\{dp[j+1][1]+a[j]|i\leq j\leq min(i+m-1,n)\}\]
\[dp[i][1]=min\{dp[j+1][0]-a[j]|i\leq j\leq min(i+m-1,n)\}\]
\[dp[i]=max\{-dp[j+1]+a[j]|i\leq j\leq min(i+m-1,n)\}\]
#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const int INF=1e9;
int n,m;
ll a[N],dp[N][2],q[N],p[N],head,tail,h,t;
int main(){
freopen("game.in","r",stdin);
freopen("game.out","w",stdout);
scanf("%d%d",&n,&m);
for(register int i=1;i<=n;i++)scanf("%lld",&a[i]);
q[head=tail=1]=n;p[h=t=1]=n;
for(register int i=n;i>=1;i--){
while(head<=tail&&dp[q[tail]+1][1]+a[q[tail]]<=dp[i+1][1]+a[i])tail--;
q[++tail]=i;
while(h<=t&&dp[p[t]+1][0]-a[p[t]]>=dp[i+1][0]-a[i])t--;
p[++t]=i;
while(head<=tail&&q[head]>=i+m)head++;
dp[i][0]=dp[q[head]+1][1]+a[q[head]];
while(h<=t&&p[h]>=i+m)h++;
dp[i][1]=dp[p[h]+1][0]-a[p[h]];
}
printf("%lld\n%lld\n",dp[1][0],dp[1][1]);
fclose(stdin);fclose(stdout);
return 0;
}
至于丁国国王的下场……
大魔王一气之下把他扔进了迷雾森林。迷雾森林可以看作一棵有 n 个节点的树,根节点为 \(1\),但由于“Birds are everywhere.”,他得到了种种不一样的消息,每份消息中都会告诉他有两棵子树是禁忌之地,于是他向你求助了。
他给出了 \(q\) 个形如x y
的询问,表示他不能走到 \(x\) 和 \(y\) 的子树中,由于走的路径越长他找到出口的概率越大并且他 只能走一条不经过重复节点的路径,现在他想知道对于每组询问他能走的最长路径是多少,如果没有,输出零。
你刚刚在对决中打败了大魔王,心情愉悦,决定帮丁国国王一把。
当然,出于本国利益,你也可以不帮他。
第一行两个正整数 \(n\) 和 \(q\)(\(1 \leq n,q \leq 100000\))
第二到第 n 行每行两个整数 \(u,v\) 表示 \(u\) 和 \(v\) 之间有一条边连接,边的长度为 \(1\)。
接下来 \(q\) 行每行两个 \(x,y\) 表示一组询问,意义如题目描述。
q 行,输出见题目描述
input
5 2
1 3
3 2
3 4
2 5
2 4
5 4
outpu
1
2
询问 \(1\) 中 \(2\) 和 \(4\) 的子树不能走,最长路径为\((1,3)\)长度为 \(1\)
询问 \(2\) 中 \(5\) 和 \(4\) 的子树不能走,最长路径为\((1,3,2)\)长度为 \(2\)
对于前 \(20\%\)的数据:\(1 \leq n,q \leq 100\)
对于前 \(50\%\)的数据:\(1 \leq n,q \leq 2000\)
对于 \(100\%\) 的数据:\(1 \leq n \leq 100000\) , \(1 \leq m \leq 50000\)
时间限制:1s
空间限制:512MB
#include<cstdio>
#include<iostream>
using namespace std;
const int N=1e5+10;
int n,q,U,V,head[N],cnt,pre[N],las[N],p[N],dep[N<<1],depth[N],anc[N<<1][20],vk[N<<1],cl,cll,num[N],x,y;
struct edge{int nxt,to;}ed[N<<1];
struct data{int x,y;}seg[N<<2],ans;
inline int read(){
int h=0;char ch=‘ ‘;while(ch<‘0‘||ch>‘9‘)ch=getchar();
while(ch>=‘0‘&&ch<=‘9‘)h=h*10+ch-‘0‘,ch=getchar();return h;}
inline void addedge(int x,int y){
ed[++cnt].to=y;ed[cnt].nxt=head[x];head[x]=cnt;
ed[++cnt].to=x;ed[cnt].nxt=head[y];head[y]=cnt;}
inline void DFS(int u,int fa,int de){
dep[++cll]=de;vk[cll]=u;p[u]=cll;pre[u]=++cl;num[cl]=u;depth[u]=de;
for(register int i=head[u];i;i=ed[i].nxt){
int v=ed[i].to;if(v==fa)continue;
DFS(v,u,de+1);dep[++cll]=de;vk[cll]=u;p[u]=cll;}
las[u]=cl;}
inline void Preprocess(){
for(register int i=1;i<=cll;i++)anc[i][0]=i;
for(register int j=1;(1<<j)<=cll;j++)
for(register int i=1;i+(1<<j)-1<=cll;i++){
int a=anc[i][j-1],b=anc[i+(1<<(j-1))][j-1];
anc[i][j]=dep[a]<=dep[b]? a:b;}
}
inline int LCA(int x,int y){
int L=p[x],R=p[y],LOG=0;if(L>R)swap(L,R);
while(1<<(LOG+1)<R-L+1)LOG++;
int a=anc[L][LOG],b=anc[R-(1<<LOG)+1][LOG];
return dep[a]<=dep[b]? vk[a]:vk[b];}
inline int dis(int x,int y){return depth[x]+depth[y]-(depth[LCA(x,y)]<<1);}
inline data merge(data a,data b){
if(!a.x)return b;if(!b.x)return a;
int val=dis(a.x,a.y),w;data c=a;
if((w=dis(a.x,b.x))>val)val=w,c.x=a.x,c.y=b.x;
if((w=dis(a.x,b.y))>val)val=w,c.x=a.x,c.y=b.y;
if((w=dis(a.y,b.x))>val)val=w,c.x=a.y,c.y=b.x;
if((w=dis(a.y,b.y))>val)val=w,c.x=a.y,c.y=b.y;
if((w=dis(b.x,b.y))>val)val=w,c.x=b.x,c.y=b.y;
return c;}
inline void build(int o,int L,int R){
if(L==R){seg[o]=(data){num[L],num[L]};return;}
int M=(L+R)>>1,lc=o<<1,rc=(o<<1)+1;
build(lc,L,M);build(rc,M+1,R);
seg[o]=merge(seg[lc],seg[rc]);}
inline data query(int o,int L,int R,int l,int r){
if(l<=L&&R<=r)return seg[o];
int M=(L+R)>>1,lc=o<<1,rc=(o<<1)+1;data c=(data){0,0};
if(l<=M)c=merge(c,query(lc,L,M,l,r));if(r>M)c=merge(c,query(rc,M+1,R,l,r));
return c;}
int main(){
freopen("find.in","r",stdin);freopen("find.out","w",stdout);
n=read();q=read();
for(register int i=1;i<n;i++)
U=read(),V=read(),addedge(U,V);
DFS(1,0,1);Preprocess();build(1,1,n);
while(q--){
x=read();y=read();ans=(data){0,0};
if(x==1||y==1){printf("0\n");continue;}
int l1=pre[x],r1=las[x],l2=pre[y],r2=las[y];
if(l1>l2)swap(l1,l2),swap(r1,r2);
if(l1<=l2&&r2<=r1){
if(1<=l1-1)ans=merge(ans,query(1,1,n,1,l1-1));
if(r1+1<=n)ans=merge(ans,query(1,1,n,r1+1,n));}
else{
if(1<=l1-1)ans=merge(ans,query(1,1,n,1,l1-1));
if(r1+1<=l2-1)ans=merge(ans,query(1,1,n,r1+1,l2-1));
if(r2+1<=n)ans=merge(ans,query(1,1,n,r2+1,n));}
printf("%d\n",dis(ans.x,ans.y));
}
fclose(stdin);fclose(stdout);
return 0;
}
标签:oid game 优化 模拟 amp eve wap ++ 结束
原文地址:https://www.cnblogs.com/ForwardFuture/p/9845009.html