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

  

posted @ 2020-09-01 03:41  风生  阅读(93)  评论(0编辑  收藏  举报