TC SRM 680(div 2) 1000pts

题意:

It’s a well-known fact that Limak, as every bear, owns a set of numbers. You know some information about the set:
The elements of the set are distinct positive integers.
The number of elements in the set is n. The number n is divisible by 3.
All elements are between 1 and b, inclusive: bears don’t know numbers greater than b.
For each r in {0,1,2}, the set contains exactly n/3 elements that give remainder r when divided by 3. (That is, there are n/3 elements divisible by 3, n/3 elements of the form 3k+1, and n/3 elements of the form 3k+2.)
Limak smiles mysteriously and gives you q hints about his set. The hints are numbered 0 through q-1. For each valid i, the hint number i is the following sentence: “If you only look at elements that are between 1 and upTo[i], inclusive, you will find exactly quantity[i] such elements in my set.”
In a moment Limak will tell you the actual puzzle, but something doesn’t seem right… That smile was very strange. You start to think about a possible reason. Maybe Limak cheated you? Or is he a fair grizzly bear?
You are given the ints n and b. You are also given the vector s upTo and quantity. Return “fair” (quotes for clarity) if there exists at least one set that has all the required properties and matches all the given hints. Otherwise, return “unfair”.

思路:

网络流搞!
没时间写了,赛后过题,泪奔!
1b 每个数看成一个点,设 s0 , s1 , s2 分别为模3后的余数为0,1,2的点集,源点 S s0, s1 , s2 连边,流量均为 n3
s0 , s1 , s2 分别向对应点集连边,流量为1;
对于所有的询问,排完序我们可以得到每个区间 [L,R] 内有 Vi 个点出现在最终满足条件点集中,把每个区间看作一个点 Ci ,由区间内的点向 Ci 连边,流量为1,由 Ci 向 汇点 T 连边,流量为 Vi
最后跑一遍最大流,看是否满流即可!

啥都别说了!
TC

代码:
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <string>
#define PB push_back
#define FT first
#define SD second
#define MP make_pair
#define INF 0x3f3f3f3f
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int>  P;
vector<P> V;
bool cmp(const P a, const P b)
{
    if(a.FT == b.FT) return a.SD < b.SD;
    return a.FT < b.FT;
}
const int N = 1100,M = 5+1e5,MOD=7+1e9;
struct Node
{
    int from,to,next;
    int cap;
}edge[M];
int tol;

int dep[N];//dep为点的层次
int head[N];

void init()
{
    tol=0;
    memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w)//第一条变下标必须为偶数
{
    edge[tol].from=u;
    edge[tol].to=v;
    edge[tol].cap=w;//注意正向边流量值
    edge[tol].next=head[u];
    head[u]=tol++;

    edge[tol].from=v;
    edge[tol].to=u;
    edge[tol].cap=0;//注意反向边的流量值
    edge[tol].next=head[v];
    head[v]=tol++;
}

int BFS(int start,int end)
{
    int que[N];
    int front,rear;
    front=rear=0;
    memset(dep,-1,sizeof(dep));
    que[rear++]=start;
    dep[start]=0;
    while(front!=rear)
    {
        int u=que[front++];
        if(front==N)front=0;
        for(int i=head[u];i!=-1;i=edge[i].next)
        {
            int v=edge[i].to;
            if(edge[i].cap>0&&dep[v]==-1)
            {
                dep[v]=dep[u]+1;
                que[rear++]=v;
                if(rear>=N)rear=0;
                if(v==end)return 1;
            }
        }
    }
    return 0;
}
int dinic(int start,int end)
{
    int res=0;
    int top;
    int stack[N];//stack为栈,存储当前增广路
    int cur[N];//存储当前点的后继
    while(BFS(start,end))
    {
        memcpy(cur,head,sizeof(head));
        int u=start;
        top=0;
        while(1)
        {
            if(u==end)
            {
                int min=INF;
                int loc;
                for(int i=0;i<top;i++)
                  if(min>edge[stack[i]].cap)
                  {
                      min=edge[stack[i]].cap;
                      loc=i;
                  }
                for(int i=0;i<top;i++)
                {
                    edge[stack[i]].cap-=min;
                    edge[stack[i]^1].cap+=min;
                }
                res+=min;
                top=loc;
                u=edge[stack[top]].from;
            }
            for(int i=cur[u];i!=-1;cur[u]=i=edge[i].next)
              if(edge[i].cap!=0&&dep[u]+1==dep[edge[i].to])
                 break;
            if(cur[u]!=-1)
            {
                stack[top++]=cur[u];
                u=edge[cur[u]].to;
            }
            else
            {
                if(top==0)break;
                dep[u]=-1;
                u=edge[stack[--top]].from;
            }
        }
    }
    return res;
}
class BearFair2 {
    public:
    string isFair(int n, int b, vector <int> upTo, vector <int> quantity) {
        int Q = upTo.size();
        V.clear();
        V.PB(MP(b, n)), V.PB(MP(0, 0));
        for(int i = 0;i < Q;i ++) {
            V.PB(MP(upTo[i], quantity[i]));
        }
        sort(V.begin(), V.end(), cmp);
        bool ok = 1;
        for(int i = 1;i < V.size();i ++) {
            int x = V[i].FT - V[i-1].FT;
            if(V[i].SD < V[i-1].SD || V[i].SD - V[i-1].SD > x) {
                ok = 0;
                break;
            }
        }
        if(!ok) return "unfair";
        init();
        int S0 = b + Q + 3, S1 = S0 + 1, S2 = S0 + 2, S = S2 + 1, T = S + 1;
        addedge(S, S0, n/3), addedge(S, S1, n/3), addedge(S, S2, n/3);
        for(int i = 1;i <= b;i ++) {
            if(i % 3 == 0) addedge(S0, i, 1);
            else if(i % 3 == 1) addedge(S1, i, 1);
            else addedge(S2, i, 1);
        }
        for(int i = 1;i < V.size();i ++) {
            for(int j = V[i-1].FT + 1;j <= V[i].FT;j ++) {
                addedge(j, b + i, 1);
            }
            addedge(b + i, T, V[i].SD - V[i-1].SD);
        }
        return dinic(S, T) == n ? "fair" : "unfair";
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值