JZOJ 3326 矮人排队
题目
交换两个位置上的数,或者查询权值区间 [ l ∼ r ] [l\sim r] [l∼r]是否连续
分析
用权值线段树,维护区间最大值和区间最小值的位置,判断是否连续
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define swap(a,b) (a^=b,b^=a,a^=b)
using namespace std;
const int N=201001;
int w1[530001],w2[530001],pos[N],n,bas,m;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
inline void pdown(int k){w1[k]=min(w1[k<<1],w1[k<<1|1]),w2[k]=max(w2[k<<1],w2[k<<1|1]);}
inline void update(int x,int y){
w1[x+bas]=w2[x+bas]=y;
for (x+=bas,x>>=1;x;x>>=1) pdown(x);
}
inline void query(int x,int y){
rr int ans1=w1[0],ans2=0,t1=x,t2=y;
for (x+=bas-1,y+=bas+1;x^y^1;x>>=1,y>>=1){
if (!(x&1)) ans1=min(ans1,w1[x^1]),ans2=max(ans2,w2[x^1]);
if (y&1) ans1=min(ans1,w1[y^1]),ans2=max(ans2,w2[y^1]);
}
ans2+t1==t2+ans1?printf("YES\n"):printf("NO\n");
}
signed main(){
n=iut(); m=iut(); for (bas=1;(bas<<=1)<n+3;); memset(w1,42,sizeof(w1));
for (rr int i=1,x;i<=n;++i) x=iut(),w1[bas+x]=w2[bas+x]=i,pos[i]=x;
for (rr int i=bas-1;i;--i) pdown(i);
for (rr int i=1;i<=m;++i){
rr int q=iut(),x=iut(),y=iut();
if (!(q&1)) query(x,y);
else update(pos[x],y),update(pos[y],x),swap(pos[x],pos[y]);
}
return 0;
}
JZOJ 3237 间谍派遣(怀疑是和B组第二题对调了,因为这道题秒切)
BZOJ 3482 hiperprostor JZOJ 3238 超空间旅行
题目
给出一个有向图,一些边权是变量x,多组询问两点间可能路径个数和可能路径的总和
分析
那么可能路径能表示出 y = k x + b y=kx+b y=kx+b的形式,那么跑最短路求出k和b,再维护上凸壳,每一段用等差数列算出答案,bzoj貌似卡spfa,于是我就打了dijkstra,结果jzojTLE了,所以我就吸了好多口氧,如果我码完SPFA再说吧
代码
#include <cstdio>
#include <cctype>
#include <cstring>
#include <queue>
#define rr register
using namespace std;
const int inf=707406378; double b[501];
struct node{int y,w,next;}e[10011]; bool v[501][501];
int n,m,ls[501],dis[501][501],a[501],s,t,cnt;
inline signed iut(){
rr int ans=0; rr char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
return ans;
}
struct rec{
int x,y,dist;
bool operator <(const rec &t)const{
return dist!=t.dist?dist<t.dist:y<t.y;
}
}heap[500011];
inline void Push(rec d){
heap[++cnt]=d;
rr int x=cnt;
while (x>1){
if (heap[x]<heap[x>>1])
swap(heap[x>>1],heap[x]),x>>=1;
else return;
}
}
inline void Pop(){
heap[1]=heap[cnt--];
rr int x=1;
while ((x<<1)<=cnt){
rr int y=x<<1;
if (y<cnt&&heap[y+1]<heap[y]) ++y;
if (heap[y]<heap[x]) swap(heap[y],heap[x]),x=y;
else return;
}
}
inline void spfa(){
memset(dis,42,sizeof(dis)),memset(v,0,sizeof(v));
heap[cnt=1]=(rec){s,0,0},dis[s][0]=0,v[s][0]=1;
while (cnt){
rr rec p=heap[1]; Pop(); v[p.x][p.y]=1;
if (dis[p.x][p.y]!=p.dist) continue;
for (rr int i=ls[p.x];i;i=e[i].next)
if (p.y+(!e[i].w)<=n&&dis[e[i].y][p.y+(!e[i].w)]>dis[p.x][p.y]+e[i].w){
rr int zx=e[i].y,zy=p.y+(!e[i].w);
dis[zx][zy]=dis[p.x][p.y]+e[i].w;
if (!v[zx][zy]) Push((rec){zx,zy,dis[zx][zy]});
}
}
}
inline long long add(int k,int b,int l,int r){return (1ll*k*(l+r)+b*2)*(r-l+1)>>1;}
inline double slope(int x,int y){return 1.0*(dis[t][y]-dis[t][x])/(x-y);}
inline void answ(){
spfa(); rr int flag=0;
for (rr int ttt=0;ttt<=n;++ttt) if (dis[t][ttt]!=inf) {flag=1; break;}
if (!flag) {printf("0 0\n"); return;}
if (dis[t][0]==inf) {printf("inf\n"); return;}
rr int top=0;
for (rr int i=n;~i;--i){
if (dis[t][i]==inf) continue;
while (top&&b[top]>=slope(a[top],i)) --top;
if (top) b[top+1]=slope(a[top],i); a[++top]=i;
}
rr int sum=b[top]; rr long long ans=0;
for (rr int i=1;i<top;++i) ans+=add(a[i],dis[t][a[i]],(int)b[i]+1,(int)b[i+1]);
if (sum*a[top-1]+dis[t][a[top-1]]!=dis[t][0]||top==1) ans+=dis[t][0],++sum;
printf("%d %lld\n",sum,ans);
}
signed main(){
n=iut(); m=iut();
for (rr int i=1;i<=m;++i){
rr int x=iut(),y=iut(),w=0; rr char c=getchar();
if (c!='x') while (isdigit(c)) w=(w<<3)+(w<<1)+(c^48),c=getchar();
e[i]=(node){y,w,ls[x]},ls[x]=i;
}
for (rr int q=iut();q;--q) s=iut(),t=iut(),answ();
return 0;
}