2020/8/31
英语四级
学习替罪羊树 划分树
四题




#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define inf 1e9+7
inline int read(){
int s = 0, w = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
return s * w;
}
const int N = 5010, M = 200010;
int ver[M], edge[M], cost[M], Next[M], head[N];
int d[N], incf[N], pre[N], v[N],a[N];
int n, k, tot, s, t, maxflow, ans;
void add(int x, int y, int z, int c) {
// 正向边,初始容量z,单位费用c
ver[++tot] = y, edge[tot] = z, cost[tot] = c;
Next[tot] = head[x], head[x] = tot;
// 反向边,初始容量0,单位费用-c,与正向边“成对存储”
ver[++tot] = x, edge[tot] = 0, cost[tot] = -c;
Next[tot] = head[y], head[y] = tot;
}
bool spfa() {
queue<int> q;
for(int i = 0; i < N; i ++) d[i] = inf;
memset(v, 0, sizeof(v));
q.push(s); d[s] = 0; v[s] = 1; // SPFA 求最长路
incf[s] = 1 << 30; // 增广路上各边的最小剩余容量
while (q.size()) {
int x = q.front(); v[x] = 0; q.pop();
for (int i = head[x]; i; i = Next[i]) {
if (!edge[i]) continue; // 剩余容量为0,不在残量网络中,不遍历
int y = ver[i];
if (d[y]>d[x] + cost[i]) {
d[y] = d[x] + cost[i];
incf[y] = min(incf[x], edge[i]);
pre[y] = i; // 记录前驱,便于找到最长路的实际方案
if (!v[y]) v[y] = 1, q.push(y);
}
}
}
if (d[t] == inf) return false; // 汇点不可达,已求出最大流
return true;
}
// 更新最长增广路及其反向边的剩余容量
void update() {
int x = t;
while (x != s) {
int i = pre[x];
edge[i] -= incf[t];
edge[i ^ 1] += incf[t]; // 利用“成对存储”的xor 1技巧
x = ver[i ^ 1];
}
maxflow += incf[t];
ans += d[t] * incf[t];
}
int main() {
n = read(); int sum = 0;
s = n * 2 + 1; t = s + 1;
tot = 1; // 一会儿要从2开始“成对存储”,2和3是一对,4和5是一对
for (int i = 1; i <= n; i++){
a[i] = read();
sum += a[i];
}
sum /= n;
for(int i = 1; i <= n; i ++){
a[i] -= sum;
if(a[i] < 0) {
add(i + n,t,-a[i],0);
} else {
add(s,i,a[i],0);
}
if(i - 1 > 0) {
add(i,i - 1,inf,1);
add(i,i - 1 + n,inf,1);
}
if(i + 1 <= n) {
add(i,i + 1,inf,1);
add(i,i + 1 + n,inf,1);
}
}
add(1,n,inf,1);
add(1,n << 1,inf,1);
add(n,1,inf,1);
add(n,1 + n,inf,1);
while (spfa()) {update();} // 计算最大费用最大流
cout << ans << endl;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define inf 1e9+7
inline int read(){
int s = 0, w = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
return s * w;
}
const int N = 5010, M = 200010;
int ver[M], edge[M], cost[M], Next[M], head[N];
int d[N], incf[N], pre[N], v[N],m;
int n, k, tot, s, t, maxflow, ans;
int a[205][205],b[205][205],c[205][205][205];
int need[205],sup[205],cnt;
void add(int x, int y, int z, int c) {
// 正向边,初始容量z,单位费用c
ver[++tot] = y, edge[tot] = z, cost[tot] = c;
Next[tot] = head[x], head[x] = tot;
// 反向边,初始容量0,单位费用-c,与正向边“成对存储”
ver[++tot] = x, edge[tot] = 0, cost[tot] = -c;
Next[tot] = head[y], head[y] = tot;
}
bool spfa() {
queue<int> q;
for(int i = 0; i < N; i ++) d[i] = inf;
memset(v, 0, sizeof(v));
q.push(s); d[s] = 0; v[s] = 1; // SPFA 求最长路
incf[s] = 1 << 30; // 增广路上各边的最小剩余容量
while (q.size()) {
int x = q.front(); v[x] = 0; q.pop();
for (int i = head[x]; i; i = Next[i]) {
if (!edge[i]) continue; // 剩余容量为0,不在残量网络中,不遍历
int y = ver[i];
if (d[y]>d[x] + cost[i]) {
d[y] = d[x] + cost[i];
incf[y] = min(incf[x], edge[i]);
pre[y] = i; // 记录前驱,便于找到最长路的实际方案
if (!v[y]) v[y] = 1, q.push(y);
}
}
}
if (d[t] == inf) return false; // 汇点不可达,已求出最大流
return true;
}
// 更新最长增广路及其反向边的剩余容量
void update() {
int x = t;
while (x != s) {
int i = pre[x];
edge[i] -= incf[t];
edge[i ^ 1] += incf[t]; // 利用“成对存储”的xor 1技巧
x = ver[i ^ 1];
}
maxflow += incf[t];
ans += d[t] * incf[t];
}
int mincost(){
ans = 0;
while (spfa()) {update();} // 计算最大费用最大流
return ans;
}
int main() {
while(~scanf("%d%d%d",&n,&m,&k)){
if(n == 0) break;
memset(need,0,sizeof(need));
memset(sup,0,sizeof(sup));
s = n + m + 1; t = s + 1;
tot = 1; // 一会儿要从2开始“成对存储”,2和3是一对,4和5是一对
for(int i=1;i<=n;i++)
for(int j=1;j<=k;j++){
a[i][j] = read();
need[j]+=a[i][j];
}
for(int i=1;i<=m;i++)
for(int j=1;j<=k;j++){
b[i][j] = read();
sup[j]+=b[i][j];
}
for(int i=1;i<=k;i++)//最小花费
for(int j=1;j<=n;j++)
for(int l=1;l<=m;l++)
c[i][j][l] = read();
int flag=0;
for(int i=1;i<=k;i++){
if(sup[i]<need[i]){
flag=1;
}
}
if(flag){
printf("-1\n");continue;
}
int ans = 0;
for(int i=1;i<=k;i++)
{
memset(head,0,sizeof(head));cnt=0;
for(int j=1;j<=m;j++)
add(s,j,b[j][i],0);
for(int j=1;j<=n;j++)
add(j+m,t,a[j][i],0);
for(int j=1;j<=n;j++)
for(int l=1;l<=m;l++){
add(l,j+m,inf,c[i][j][l]);
}
ans+=mincost();
}
printf("%d\n",ans);
}
#include <bits/stdc++.h>
using namespace std;
const int N=1e4+5;
struct edge{
double x,y1,y2;
int k;
bool operator <(const edge &t)const
{
return x<t.x;
}
}op[N*2];
struct node{
int l,r,cnt;
double len;
}tr[N*8];
vector<double>v;
void pushup(int u)
{
if(tr[u].cnt)
{
tr[u].len=v[tr[u].r+1]-v[tr[u].l];
}
else if(tr[u].l!=tr[u].r)
{
tr[u].len=tr[u<<1].len+tr[u<<1|1].len;
}
else
{
tr[u].len=0;
}
}
void modify(int u,int l,int r,int k)
{
if(l<=tr[u].l&&r>=tr[u].r)
{
tr[u].cnt+=k;
pushup(u);
return;
}
else
{
int mid=tr[u].l+tr[u].r>>1;
if(l<=mid) modify(u<<1,l,r,k);
if(r>mid) modify(u<<1|1,l,r,k);
pushup(u);
}
}
void build(int u,int l,int r)
{
if(l==r)
{
tr[u]={l,r,0,0};
return;
}
else
{
int mid=l+r>>1;
tr[u]={l,r,0,0};
build(u<<1,l,mid);
build(u<<1|1,mid+1,r);
}
}
int find(double x)//寻找x的位子
{
return lower_bound(v.begin(),v.end(),x)-v.begin();
}
int main()
{
int n,T=1;
while(cin>>n,n)
{
v.clear();
for(int i=0,j=0;i<n;i++)
{
double x1,y1,x2,y2;
scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);
op[j++]={x1,y1,y2,1};
op[j++]={x2,y1,y2,-1};
v.push_back(y1);v.push_back(y2);
}
sort(v.begin(),v.end());
v.erase(unique(v.begin(),v.end()),v.end());
build(1,0,v.size()-2);
sort(op,op+2*n);
double ans=0.0;
for(int i=0;i<2*n;i++)
{
if(i>0) ans+=tr[1].len*(op[i].x-op[i-1].x);
modify(1,find(op[i].y1),find(op[i].y2)-1,op[i].k);
}
printf("Test case #%d\n",T++);
printf("Total explored area: %.2lf\n",ans);
puts("");
}
return 0;
}
}、
#include"vector"
#include"queue"
#include"algorithm"
using namespace std;
#define OK printf("\n");
#define Debug printf("this_ok\n");
#define INF 1e18
typedef long long ll;
#define scanll(a,b) scanf("%lld%lld",&a,&b);
#define scanl(a) scanf("%lld",&a);
#define printl(a,b) if(b == 0) printf("%lld ",a); else printf("%lld\n",a);
#define print_int(a,b) if(b == 0) printf("%d ",a); else printf("%d\n",a);
typedef pair<int,int> PII;
inline int read(){
int s = 0, w = 1; char ch = getchar();
while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); }
while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); }
return s * w;
}
const ll mod = 998244353;
const int N = 50010,M = 300010;
const int inf = 1 << 29;
const int dirx[4] = {-1,0,1,0};
const int diry[4] = {0,1,0,-1};
typedef struct Node{
ll x,y,w;
Node(){};
Node(ll a,ll b,ll c){x = a; y = b; w = c;}
}Node;
Node node[N];
int n,w,h;
int cmpx(Node a,Node b){
return a.x < b.x;
}
int cmpy(Node a,Node b){
return a.y < b.y;
}
ll max_into(int i,int j){
// printf("i = %d j = %d\n",i,j);
Node temp[30010];int top = 0;
int x =i;
for(i;i <= j; i ++)
temp[++ top] = node[i];
i = x;
sort(temp + 1,temp + 1 + top,cmpy);
ll value = 0,ans = 0;
ll pre = -1;
//for(int i = 1; i <= top; i ++)
for(int i = 1; i <= top;i ++){
if(pre == -1 || temp[i].y - temp[pre].y < h){
ans += temp[i].w; value = max(ans,value);
if(pre == -1) pre = i;
continue;
}
while(pre <= i && temp[i].y - temp[pre].y >= h){
ans -= temp[pre].w;
pre ++;
}
}
//printf("value = %lld\n",value);
return value;
}
int main(){
while(~scanf("%d%d%d",&n,&w,&h)){
for(int i = 1; i <= n; i ++)
scanf("%lld%lld%lld",&node[i].x,&node[i].y,&node[i].w);
sort(node + 1,node + 1 + n,cmpx);
ll ans = 0;
for(int i = 1; i <= n;i ++){
int j = i;
while(j < n && node[j + 1].x - node[i].x < w) j ++;
ans = max(ans,max_into(i,j));
}
printf("%lld\n",ans);
}
}
浙公网安备 33010602011771号