gym102394 2019CCPC哈尔滨 A. Artful Paintings(二分 差分约束 优化)

简介: gym102394 2019CCPC哈尔滨 A. Artful Paintings(二分 差分约束 优化)

linkkk

题意:

有n个方块,m 1个限制条件1,m 2个限制条件2,限制条件的描述如下:

1 : l , r , k表示区间[ l , r ]染色的方块数至少k个

2 : l , r , k表示除区间[ l , r ]染色的方块数至少k 个

思路:

如果只有条件1 11的话就是A B C 216的G了(传送门)

当时有贪心跟差分约束两种解法,但是加了条件2的话,就只能差分约束了。

先把条件都列出来,设s u m i

表示[ 1 , i ]中染色的方块数。

对于条件1 11的约束有:

sumrsuml1>=k

移项变成了s u m l − 1 − s u m r > = k − s u m

由于这个式子有三个变量,可以考虑二分s u m n,即二分染色的总方块数。

因为每个限制条件都是至少为k,所以答案是具有单调性的,如果说染色x个可以,染色x + 1个也一定满足条件。

还有一些合理性的约束:

0<=sumi−sumi−1<=1m i d < = s u m n − s u m,这个是为了保证s u m n − s u m 0 = = m i d 的。

建图,想跑最短路的话,松弛条件为d i s v < = d i s u + w,建边从u − > v,权值为w,也就是d i s v − d i s u < = w,后者向前者连边。


具体做法,二分染色的总方块数,每次c h e c k的时候,建图跑最短路,用s p f a判断有没有负环。

这样可能还是会TLE,加一个判断负环的小优化:如果在最短路过程中d i s i < 0就一定存在负环,因为在上面的连边过程中,从i − > i − 1有一条权值为0的边了。

最长路解法博客

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 6;
#define debug(x) cout << #x << ":" << x << endl;
#define mst(x, a) memset(x, a, sizeof(x))
#define rep(i, a, b) for (int i = (a); i <= (b); ++i)
int n,m1,m2,S,T;
struct Node{
  int l,r,k,op;
};
vector<Node>Q;
vector< pair<int,int> >e[maxn];
int vis[maxn],d[maxn],dist[maxn];
int  spfa(int S)
{
  int flag=0;
  queue<int>q;
  q.push(S);
  while(q.size())
  {
    int fr = q.front();
    q.pop();
    vis[fr]  =0 ;
    if(flag) break;
    for(auto frr:e[fr])
    {
      int v = frr.first;
      int w = frr.second;
      if(dist[v]>dist[fr]+w)
      {
        dist[v] = dist[fr] + w;
        if(vis[v]==0) vis[v]  = 1,q.push(v),d[v]++;
        if(d[v]>n+1) 
        {
          flag=1;
          break;
        }
        if(dist[v]<0) return 1;
      }
    }
  }
  return flag;
}
int ok(int mid)
{
  rep(i,0,n) e[i].clear(),vis[i] =0 ,d[i] =0 ,dist[i] =1e9 ;
  dist[0] =0 ;vis[0]=1;d[0]=1;
  rep(i,1,n)
  {
    e[i-1].push_back({i,1});
    e[i].push_back({i-1,0});
  }
  for(Node fr:Q)
  {
    int l = fr.l;
    int r = fr.r;
    int op = fr.op;
    int k = fr.k;
    if(k>mid) return 0;
    if(op==1)
    {
      e[r].push_back({l-1,-k});
    }
    else
    {
      int T = k - mid;
      e[l-1].push_back({r,-T});
    }
  }
  e[0].push_back({n,mid});
  e[n].push_back({0,-mid});
  return (!spfa(S));
}
int main() {
    int _;scanf("%d",&_);
    while (_--) {
      scanf("%d",&n);
        scanf("%d",&m1);
          scanf("%d",&m2);
          Q.clear();
      S =  0;
    //  T = n + 4;
      for(int i=1 ;i<=m1 ;i++)
      {
        int l,r,k;scanf("%d%d%d",&l,&r,&k);
        Q.push_back({l,r,k,1});
      }
      for(int i=1 ;i<=m2 ;i++)
      {
        int l,r,k;scanf("%d%d%d",&l,&r,&k);
        Q.push_back({l,r,k,2});
      }
  //  cout<<"##"<<endl;
      //for(int i=0;i<=n;i++) cout<<ok(i)<<endl;
        int L = 0,R = n ,ans=-1;
      while(L<=R)
      {
        int mid = (L+R)>>1;
        if(ok(mid)) ans = mid,R = mid- 1;
        else L = mid + 1;
      } 
      printf("%d\n",ans);
    }
    return 0;
}
/*
*/



目录
相关文章
|
8月前
|
C语言
快速幂+高精乘(填坑)洛谷1226+1045
快速幂+高精乘(填坑)洛谷1226+1045
概率论期中考试究极抱佛脚
概率论期中考试究极抱佛脚
|
8月前
|
固态存储 算法 计算机视觉
CV目标检测 Task04:不讲武德-炼丹与品尝 终于,神功初成,可以开始施展拳脚了 打卡笔记
CV目标检测 Task04:不讲武德-炼丹与品尝 终于,神功初成,可以开始施展拳脚了 打卡笔记
99 0
|
算法
Plant(快速幂+数学分析(没想到吧,数学无处不在))
Plant(快速幂+数学分析(没想到吧,数学无处不在))
77 0
|
算法 Go
算法练习第五天——有效数独
请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。 数字 1-9 在每一行只能出现一次。 数字 1-9 在每一列只能出现一次。 数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)
算法练习第五天——有效数独
|
安全
L3-009 长城 (30 分)(数学知识)
L3-009 长城 (30 分)(数学知识)
232 0
L3-009 长城 (30 分)(数学知识)
|
算法
基础算法练习200题11、鸡兔同笼
基础算法练习200题11、鸡兔同笼
162 0
基础算法练习200题11、鸡兔同笼
|
算法 安全 程序员
【Python 百练成钢】Python语言解决素数筛选问题的几种方式【朴素素数筛、埃氏筛、欧拉筛】
【Python 百练成钢】Python语言解决素数筛选问题的几种方式【朴素素数筛、埃氏筛、欧拉筛】
|
机器学习/深度学习
进击的奶牛(二分)
题目描述 Farmer John 建造了一个有 NN(2≤ N ≤ 100000) 个隔间的牛棚,这些隔间分布在一条直线上,坐标是 x1,,,,xn(0≤xi≤1000000000)。
205 0