12.02WC模拟题解

来源:互联网 发布:lufylegend.js 编辑:程序博客网 时间:2024/05/23 00:09

T1 海明距离

Description

设有一长度为n的初始每个位置均为0的序列A。再给定一个长度为n的01序列B。
有Q个特殊的区间[li,ri],你可以选择将A中li到ri这些位置都变为1,当然你可以选择不变。
现在你需要最小化A,B的海明距离。即最小化对应数值不同的位置数目。

Input

第一行包括一个整数n。
接下来一行n个整数,描述序列B。
输入一行一个整数Q。
接下来Q行,每行两个整数li,ri 。

Output

输出最小的海明距离。

Sample Input

输入1:
9
0 1 0 1 1 1 0 1 0
3
1 4
5 8
6 7

输入2:
15
1 1 0 0 0 0 0 0 1 0 1 1 1 0 0
9
4 10
13 14
1 7
4 14
9 11
2 6
7 8
3 12
7 13

Sample Output

输出1:
3

输出2:
5

Data Constraint
这里写图片描述

T2 图染色

Description
这里写图片描述
Input

第一行包括两个整数N,M。
接下来M行每行两个整数u,v,代表存在一条里连接 u,v的无向边。可能存在重边自环。

Output

降序输出所有不为0的F(i) 。保留6位小数输出。

Sample Input

输入1:
5 5
1 2
2 5
3 4
4 5
3 5

输入2:
5 4
1 2
2 5
5 4
4 3

Sample Output

输出1:
3.000000
2.000000

输出2:
2.800000
2.200000

Data Constraint

对于20%的数据,n,m<=100
对于40%的数据,n,m<=5000
另外有20%的数据,保证图为一个连通的简单环,且当且仅当|u-v|=1 ,存在u到v的边。
对于100%的数据,n,m<=500000

题解

对于T1,我们可以想一个朴素的dp
在朴素dp之前先说一个东西:
a数组初始为全0,b数组则有0/1,对于一个位置i,当b[i]=0时,选择i位置变1肯定是会增加距离的,当b[i]=1则相反,所以我们预先处理一个前缀和s数组。
这样我们就可以O(1)得到区间贡献啦!!
设f[i,j]表示处理了前i个区间(没有要求必选i),最右端到达j的贡献数。
我们转移的时候发现,i这一维可以省去。
那么我们就可以简化dp
只设f[i],表示处理到的区间中最右端为i的贡献。
为了保证有序,可以先对区间排序。
考虑f[i]怎么转移到f[j]
为了保证转移正确,我们可以强制当且仅当有一个区间[i,j]时才进行转移。
那么转移就是f[j]=max(f[k])+s[j]-s[i-1],这是[i,j] 区间与之前所有区间相离的情况,所以说k的取值范围是[0,i-1]。因为我们处理到[i,j]时[0,i-1]的f值肯定已经全部处理好了,所以开个线段树维护一下就可以log找出k了。
再处理相交情况。
假设[i,j]中之前已经产生贡献的最右端点为x,那么我们的转移就变成了f[j]=f[x]+s[j]-s[x]
我们发现,f[x]-s[x] 也是可以线段树维护的。

var n,i,j,k,l,inf,tot,sum,q,r,v:longint;t1,t2,next,t,head,f,s:array[0..4000000]of longint;function max(x,y:longint):longint;begin  if x>y then exit(x) else exit(y);end;procedure ad(x,y:longint);begin  inc(tot);  next[tot]:=head[x];  head[x]:=tot;  t[tot]:=y;end;procedure build(root,l,r:longint);var mid:longint;begin  if l=r then begin    if l=0 then begin      t1[root]:=0;      t2[root]:=0;    end else begin      t1[root]:=inf;      t2[root]:=inf;    end;    exit;  end;  mid:=(l+r)div 2;  build(2*root,l,mid);  build(2*root+1,mid+1,r);  t2[root]:=max(t2[2*root],t2[2*root+1]);end;function que1(root,l,r,x,y:longint):longint;var mid:longint;begin  if (l=x)and(r=y) then exit(t1[root]);  mid:=(l+r)div 2;  if y<=mid then exit(que1(2*root,l,mid,x,y));  if x>mid then exit(que1(2*root+1,mid+1,r,x,y));  exit(max(que1(2*root,l,mid,x,mid),que1(2*root+1,mid+1,r,mid+1,y)));end;function que2(root,l,r,x,y:longint):longint;var mid:longint;begin  if (l=x)and(r=y) then exit(t2[root]);  mid:=(l+r)div 2;  if y<=mid then exit(que2(2*root,l,mid,x,y));  if x>mid then exit(que2(2*root+1,mid+1,r,x,y));  exit(max(que2(2*root,l,mid,x,mid),que2(2*root+1,mid+1,r,mid+1,y)));end;procedure change(root,l,r,x,v1,v2:longint);var mid:longint;begin  if l=r then begin    t1[root]:=max(t1[root],v1);    t2[root]:=max(t2[root],v2);    exit;  end;  mid:=(l+r)div 2;  if x<=mid then begin    change(root*2,l,mid,x,v1,v2);    t1[root]:=max(t1[root*2],t1[root*2+1]);    t2[root]:=max(t2[root*2],t2[root*2+1]);  end else begin    change(root*2+1,mid+1,r,x,v1,v2);    t1[root]:=max(t1[root*2],t1[root*2+1]);    t2[root]:=max(t2[root*2],t2[root*2+1]);  end;end;begin  readln(n);  for i:=1 to n do begin    read(j);    if j=1 then s[i]:=s[i-1]+1 else s[i]:=s[i-1]-1;    if j=0 then inc(sum);  end;  inf:=-300000000;  build(1,0,n);  for i:=1 to n do f[i]:=inf;  readln(q);  for i:=1 to q do begin    readln(l,r);    ad(l,r);  end;  for i:=1 to n do begin    j:=head[i];    v:=que1(1,0,n,0,i-1);    while j<>0 do begin      f[t[j]]:=max(f[t[j]],v+s[t[j]]-s[i-1]);      if i<t[j] then f[t[j]]:=max(f[t[j]],que2(1,0,n,i,t[j]-1)+s[t[j]]);      j:=next[j];    end;    j:=head[i];    while j<>0 do begin      change(1,0,n,t[j],f[t[j]],f[t[j]]-s[t[j]]);      j:=next[j];    end;  end;  writeln(n-sum-que1(1,0,n,1,n));end.

T2 留大坑,水过的!!!!!