计蒜客NOIP模拟赛(3)D1T3 任性的国王
X 国的地图可以被看作一个两行 nn 列的网格状图。现在 X 国需要修建铁路,然而该国的国王非常小气,他只想保证位于某两列之间的所有城市互相可以到达就行了,在此基础上,他希望所花费的代价最小。
铁路可以建在任何两个相邻的点之间,使他们可以互相到达。可以作为工作人员,你已经整理出了为每一对相邻城市架设铁路所需要的花费。你需要准备好回答国王如下形式的问题。
对于 (i,j)(i,j):当前情况下,使第 ii 列到第 jj 列之间的所有城市连通的最小代价是多少(列下标从 11 开始)?注意不能用其他列的城市。
然而你还有更大的困难,随着时间变化,使用某些边作为铁路的代价会发生改变,你必须有效率地处理这些变化。
输入格式
第一行两个正整数 n,m,表示该国有 2 行 n 列以及 m个询问或者操作。
第二行 3n-2个数,前 n-1个数依次表示在第一行的 n-1 条边上修建铁路的代价。
接下来 n-1 个数,依次表示在第二行的 n-1 条边上修建铁路的代价。
最后 n 个数,依次表示在第 1列到第 n列的边上修建铁路的代价。
接下来 m 行的输入具有如下形式,K,S,T其中
若 K=1,则表示询问当前状态下,使所有第 S 列到第 T 列之间的城市连通需要的最小代价。
若 K=2,则表示位于第 1 行第 S 列的点到第 1 行第 S+1 列的点之间的边上修建铁路的代价变为 T。
若 K=3,则表示位于第 2 行第 S 列的点和第 2 行第 S+1 列的点之间的边上修建铁路的代价变为 T。
若 K=4,则表示第 S 列的边上修建铁路的代价变为 T。
输出格式
依次对每个询问,用一行输出相应的答案。
数据范围与约定
对于 30% 的数据:n,m≤2000。
另有 30% 的数据:所有竖边的代价为 0 且永不改变。
对于全部数据:n,m<10^5
所有输入和输出数据保证合法,且不超过 2^{31}-1
样例输入
4 14
2 3 4 3 1 1 1 5 4 7
1 1 2
1 2 3
1 1 3
1 2 4
2 1 5
1 1 4
4 2 1
1 1 3
1 2 3
1 2 4
3 3 100
1 3 4
1 2 4
1 1 4
样例输出
6
8
10
13
17
9
5
10
15
16
20
暴力显然可以每一次查询做一次最小生成树
一开始贪心,每一列选两个最小的边,用线段树维护,然后选一个最小的未选边
但这样显然不能保证图连通和最优
我们要想办法用数据结构来优化查询和修改,这里用线段树
w[rt][0/1][0/1]表示rt区间左,右是否有竖边的最小值
这样就可以通过左右区间合并来维护和查询
注意当区间只有一个元素时
w[rt][0][1]=a[l]+b[l]+c[l+1]
每一个节点都要算上下一个点的竖边,合并时要减去重复的竖边
详情见代码,这样是可以保证图连通的
s=t时要特判
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long lol; 7 struct XXX 8 { 9 lol a[2][2]; 10 }; 11 lol w[800001][2][2],a[200001],b[200001],c[200001]; 12 int n,m; 13 void pushup(int rt,int mid) 14 {int i,j; 15 for (i=0;i<=1;i++) 16 for (j=0;j<=1;j++) 17 { 18 w[rt][i][j]=1e9; 19 lol cost=w[rt*2][i][1]+w[rt*2+1][1][j]-c[mid+1]; 20 w[rt][i][j]=min(w[rt][i][j],cost); 21 cost=w[rt*2][i][0]+w[rt*2+1][1][j]-c[mid+1]; 22 w[rt][i][j]=min(w[rt][i][j],cost); 23 cost=w[rt*2][i][1]+w[rt*2+1][0][j]-c[mid+1]; 24 w[rt][i][j]=min(w[rt][i][j],cost); 25 } 26 } 27 void build(int rt,int l,int r) 28 { 29 if (l>r) return; 30 if (l==r) 31 { 32 lol tot=a[l]+b[l]+c[l]+c[l+1]; 33 w[rt][1][0]=tot-c[l+1]; 34 w[rt][1][1]=tot-(a[l]+b[l]+abs(b[l]-a[l]))/2; 35 w[rt][0][0]=1e9; 36 w[rt][0][1]=tot-c[l]; 37 return; 38 } 39 int mid=(l+r)/2; 40 build(rt*2,l,mid); 41 build(rt*2+1,mid+1,r); 42 pushup(rt,mid); 43 } 44 void ask(int rt,int l,int r,int L,int R,XXX &p) 45 {int i,j; 46 if (l>r) return; 47 if (l>=L&&r<=R) 48 { 49 for (i=0;i<=1;i++) 50 for (j=0;j<=1;j++) 51 p.a[i][j]=w[rt][i][j]; 52 return; 53 } 54 XXX p1,p2; 55 if (l==r) return; 56 int mid=(l+r)/2; 57 if (L>=mid+1) 58 { 59 ask(rt*2+1,mid+1,r,L,R,p2); 60 for (i=0;i<=1;i++) 61 for (j=0;j<=1;j++) 62 p.a[i][j]=p2.a[i][j]; 63 return; 64 } 65 if (R<=mid) 66 { 67 ask(rt*2,l,mid,L,R,p1); 68 for (i=0;i<=1;i++) 69 for (j=0;j<=1;j++) 70 p.a[i][j]=p1.a[i][j]; 71 return; 72 } 73 ask(rt*2,l,mid,L,R,p1); 74 ask(rt*2+1,mid+1,r,L,R,p2); 75 for (i=0;i<=1;i++) 76 for (j=0;j<=1;j++) 77 { 78 p.a[i][j]=1e9; 79 lol cost=p1.a[i][1]+p2.a[1][j]-c[mid+1]; 80 p.a[i][j]=min(p.a[i][j],cost); 81 cost=p1.a[i][0]+p2.a[1][j]-c[mid+1]; 82 p.a[i][j]=min(p.a[i][j],cost); 83 cost=p1.a[i][1]+p2.a[0][j]-c[mid+1]; 84 p.a[i][j]=min(p.a[i][j],cost); 85 } 86 } 87 void update(int rt,int l,int r,lol k,lol x,lol d) 88 { 89 if (l>r) return; 90 if (l==r) 91 { 92 if (k==2) a[x]=d; 93 if (k==3) b[x]=d; 94 if (k==4) c[x]=d; 95 lol tot=a[l]+b[l]+c[l]+c[l+1]; 96 w[rt][1][0]=tot-c[l+1]; 97 w[rt][1][1]=tot-(a[l]+b[l]+abs(b[l]-a[l]))/2; 98 w[rt][0][0]=1e9; 99 w[rt][0][1]=tot-c[l]; 100 return; 101 } 102 int mid=(l+r)/2; 103 if (k==4) 104 { 105 if (x<=mid+1) update(rt*2,l,mid,k,x,d); 106 if (x>=mid+1) update(rt*2+1,mid+1,r,k,x,d); 107 } 108 else 109 { 110 if (x<=mid) update(rt*2,l,mid,k,x,d); 111 else update(rt*2+1,mid+1,r,k,x,d); 112 } 113 pushup(rt,mid); 114 } 115 int main() 116 {int i; 117 lol k,s,t; 118 XXX p; 119 cin>>n>>m; 120 for (i=1;i<=n-1;i++) 121 scanf("%lld",&a[i]); 122 for (i=1;i<=n-1;i++) 123 scanf("%lld",&b[i]); 124 for (i=1;i<=n;i++) 125 scanf("%lld",&c[i]); 126 build(1,1,n-1); 127 while (m--) 128 {lol ans=2e9; 129 scanf("%lld%lld%lld",&k,&s,&t); 130 if (k==1) 131 { 132 if (s==t) 133 {printf("%lld\n",c[s]);continue;} 134 ask(1,1,n-1,s,t-1,p); 135 ans=min(min(p.a[0][0],p.a[0][1]),min(p.a[1][0],p.a[1][1])); 136 printf("%lld\n",ans); 137 } 138 else 139 { 140 update(1,1,n-1,k,s,t); 141 } 142 } 143 }
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long lol; 7 struct XXX 8 { 9 lol a[2][2]; 10 }; 11 lol w[800001][2][2],a[200001],b[200001],c[200001]; 12 int n,m; 13 void pushup(int rt,int mid) 14 {int i,j; 15 for (i=0;i<=1;i++) 16 for (j=0;j<=1;j++) 17 { 18 w[rt][i][j]=1e9; 19 lol cost=w[rt*2][i][1]+w[rt*2+1][1][j]-c[mid+1]; 20 w[rt][i][j]=min(w[rt][i][j],cost); 21 cost=w[rt*2][i][0]+w[rt*2+1][1][j]-c[mid+1]; 22 w[rt][i][j]=min(w[rt][i][j],cost); 23 cost=w[rt*2][i][1]+w[rt*2+1][0][j]-c[mid+1]; 24 w[rt][i][j]=min(w[rt][i][j],cost); 25 } 26 } 27 void build(int rt,int l,int r) 28 { 29 if (l>r) return; 30 if (l==r) 31 { 32 lol tot=a[l]+b[l]+c[l]+c[l+1]; 33 w[rt][1][0]=tot-c[l+1]; 34 w[rt][1][1]=tot-(a[l]+b[l]+abs(b[l]-a[l]))/2; 35 w[rt][0][0]=1e9; 36 w[rt][0][1]=tot-c[l]; 37 return; 38 } 39 int mid=(l+r)/2; 40 build(rt*2,l,mid); 41 build(rt*2+1,mid+1,r); 42 pushup(rt,mid); 43 } 44 void ask(int rt,int l,int r,int L,int R,XXX &p) 45 {int i,j; 46 if (l>r) return; 47 if (l>=L&&r<=R) 48 { 49 for (i=0;i<=1;i++) 50 for (j=0;j<=1;j++) 51 p.a[i][j]=w[rt][i][j]; 52 return; 53 } 54 XXX p1,p2; 55 if (l==r) return; 56 int mid=(l+r)/2; 57 if (L>=mid+1) 58 { 59 ask(rt*2+1,mid+1,r,L,R,p2); 60 for (i=0;i<=1;i++) 61 for (j=0;j<=1;j++) 62 p.a[i][j]=p2.a[i][j]; 63 return; 64 } 65 if (R<=mid) 66 { 67 ask(rt*2,l,mid,L,R,p1); 68 for (i=0;i<=1;i++) 69 for (j=0;j<=1;j++) 70 p.a[i][j]=p1.a[i][j]; 71 return; 72 } 73 ask(rt*2,l,mid,L,R,p1); 74 ask(rt*2+1,mid+1,r,L,R,p2); 75 for (i=0;i<=1;i++) 76 for (j=0;j<=1;j++) 77 { 78 p.a[i][j]=1e9; 79 lol cost=p1.a[i][1]+p2.a[1][j]-c[mid+1]; 80 p.a[i][j]=min(p.a[i][j],cost); 81 cost=p1.a[i][0]+p2.a[1][j]-c[mid+1]; 82 p.a[i][j]=min(p.a[i][j],cost); 83 cost=p1.a[i][1]+p2.a[0][j]-c[mid+1]; 84 p.a[i][j]=min(p.a[i][j],cost); 85 } 86 } 87 void update(int rt,int l,int r,lol k,lol x,lol d) 88 { 89 if (l>r) return; 90 if (l==r) 91 { 92 if (k==2) a[x]=d; 93 if (k==3) b[x]=d; 94 if (k==4) c[x]=d; 95 lol tot=a[l]+b[l]+c[l]+c[l+1]; 96 w[rt][1][0]=tot-c[l+1]; 97 w[rt][1][1]=tot-(a[l]+b[l]+abs(b[l]-a[l]))/2; 98 w[rt][0][0]=1e9; 99 w[rt][0][1]=tot-c[l]; 100 return; 101 } 102 int mid=(l+r)/2; 103 if (k==4) 104 { 105 if (x<=mid+1) update(rt*2,l,mid,k,x,d); 106 if (x>=mid+1) update(rt*2+1,mid+1,r,k,x,d); 107 } 108 else 109 { 110 if (x<=mid) update(rt*2,l,mid,k,x,d); 111 else update(rt*2+1,mid+1,r,k,x,d); 112 } 113 pushup(rt,mid); 114 } 115 int main() 116 {int i; 117 lol k,s,t; 118 XXX p; 119 cin>>n>>m; 120 for (i=1;i<=n-1;i++) 121 scanf("%lld",&a[i]); 122 for (i=1;i<=n-1;i++) 123 scanf("%lld",&b[i]); 124 for (i=1;i<=n;i++) 125 scanf("%lld",&c[i]); 126 build(1,1,n-1); 127 while (m--) 128 {lol ans=2e9; 129 scanf("%lld%lld%lld",&k,&s,&t); 130 if (k==1) 131 { 132 if (s==t) 133 {printf("%lld\n",c[s]);continue;} 134 ask(1,1,n-1,s,t-1,p); 135 ans=min(min(p.a[0][0],p.a[0][1]),min(p.a[1][0],p.a[1][1])); 136 printf("%lld\n",ans); 137 } 138 else 139 { 140 update(1,1,n-1,k,s,t); 141 } 142 } 143 }