zoukankan      html  css  js  c++  java
  • 洛谷1083 借教室

    原题链接

    二分+差分

    运用差分的思想,对于在([l, r])间租借(x)间教室的订单,在差分数组(设为(a[]))中只需将(a[l] + x, a[r + 1] - x)即可,最后只需要前缀和一下就可以计算出某一天需要租借的教室数量,再与当天可租借的教室数量比较大小就可以知道是否可行。
    于是我们成功将修改并判断所需复杂度降为线性,再套上一个二分答案即可。
    时间复杂度(O((n + m) log m))

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 1e6 + 10;
    struct ord {
    	int x, y, nd;
    };
    ord a[N];
    int res[N], b[N], n;
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    bool judge(int mid)
    {
    	int i;
    	memset(b, 0, sizeof(b));
    	for (i = 1; i <= mid; i++)
    		b[a[i].x] += a[i].nd, b[a[i].y + 1] -= a[i].nd;
    	for (i = 1; i <= n; i++)
    	{
    		b[i] += b[i - 1];
    		if (b[i] > res[i])
    			return true;
    	}
    	return false;
    }
    int main()
    {
    	int i, m, l = 1, r, mid, ans = 0;
    	n = re(); r = m = re();
    	for (i = 1; i <= n; i++)
    		res[i] = re();
    	for (i = 1; i <= m; i++)
    		a[i].nd = re(), a[i].x = re(), a[i].y = re();
    	while (l <= r)
    	{
    		mid = (l + r) >> 1;
    		if (judge(mid))
    		{
    			ans = mid;
    			r = mid - 1;
    		}
    		else
    			l = mid + 1;
    	}
    	if (!ans)
    		return printf("0"), 0;
    	printf("-1
    %d", ans);
    	return 0;
    }
    

    线段树

    这题用线段树也可以很方便的求解。
    以能出租的教室建立线段树,维护一个(min),修改自然就是区间减。
    当整个区间的最小值(即线段树根上储存的最小值)小于(0)时,就说明已经无法满足订单的要求了。
    时间复杂度(O(mlog n)),但因为线段树常数还是比较大的,写的丑可能就跑不过去了。

    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int N = 1e6 + 10;
    int res[N], mi[N << 2], us[N << 2];
    inline int re()
    {
    	int x = 0;
    	char c = getchar();
    	bool p = 0;
    	for (; c < '0' || c > '9'; c = getchar())
    		p |= c == '-';
    	for (; c >= '0' && c <= '9'; c = getchar())
    		x = x * 10 + c - '0';
    	return p ? -x : x;
    }
    inline int minn(int x, int y) { return x < y ? x : y; }
    void pp(int r) { mi[r] = minn(mi[r << 1], mi[r << 1 | 1]); }
    void pn(int r)
    {
    	int &k = us[r];
    	if (k)
    	{
    		int lx = r << 1, ly = r << 1 | 1;
    		us[lx] += k; us[ly] += k;
    		mi[lx] += k; mi[ly] += k;
    		k = 0;
    	}
    }
    void bu(int r, int x, int y)
    {
    	if (!(x ^ y))
    		mi[r] = res[x];
    	else
    	{
    		int mid = (x + y) >> 1;
    		bu(r << 1, x, mid);
    		bu(r << 1 | 1, mid + 1, y);
    		pp(r);
    	}
    }
    void mdf(int r, int x, int y, int ql, int qr, int k)
    {
    	if (ql <= x && y <= qr)
    	{
    		mi[r] += k; us[r] += k;
    		return;
    	}
    	int mid = (x + y) >> 1;
    	pn(r);
    	if (ql <= mid)
    		mdf(r << 1, x, mid, ql, qr, k);
    	if (mid < qr)
    		mdf(r << 1 | 1, mid + 1, y, ql, qr, k);
    	pp(r);
    }
    int main()
    {
    	int i, n, m, x, y, z;
    	n = re(); m = re();
    	for (i = 1; i <= n; i++)
    		res[i] = re();
    	bu(1, 1, n);
    	for (i = 1; i <= m; i++)
    	{
    		z = re(); x = re(); y = re();
    		mdf(1, 1, n, x, y, -z);
    		if (mi[1] < 0)
    			return printf("-1
    %d", i), 0;
    	}
    	printf("0");
    	return 0;
    }
    
  • 相关阅读:
    设计模式(第八式:适配器模式)
    设计模式(第七式:装饰模式)
    设计模式(第六式:代理模式)
    设计模式(第五式:原型模式)
    设计模式(第四式:建造者模式)
    设计模式(第三式:抽象工厂模式)
    ASP.NET C#使用JavaScriptSerializer实现序列化与反序列化得到JSON
    C#中Object转化为json对象
    C# 调用WebApi
    Winform实现调用asp.net数据接口实例
  • 原文地址:https://www.cnblogs.com/Iowa-Battleship/p/10453239.html
Copyright © 2011-2022 走看看