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); } }