URAL 1707. Hypnotoad's Secret(树阵)

URAL 1707. Hypnotoad‘s Secret

space=1&num=1707" target="_blank" style="">题目链接

题意:这题设置的恶心不能多说。构造点和矩形。大概就是问每一个矩形里面是否包括点

思路:树状数组。把点排序,按y轴,在按x轴。在按询问,这样每次遇到一个点就在对应的扫描线上加。遇到查询就询问出左边到这个点位置的,就能预处理出每一个点左下角包括的点的个数,然后每一个矩形再利用容斥原理去搞一下就可以

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
using namespace std;

typedef long long ll;

const int N = 1050005;
const int M = 5005;

const ll MOD = 200904040930 + 33;

struct Point {
	int x, y;
	bool isop;
	Point() {}
	Point(int x, int y, bool isop) {
		this->x = x;
		this->y = y;
		this->isop = isop;
	}
} p[N];

bool cmp(Point a, Point b) {
	if (a.y == b.y) {
		if (a.x == b.x)
			return a.isop < b.isop;
		return a.x < b.x;
	}
	return a.y < b.y;
}

int pn;

int n, m;

struct OP {
	int a0, b0, c0, d0;
	int da, db, dc, dd;
	int q;
	void read() {
		scanf("%d%d%d%d%d%d%d%d%d", &a0, &b0, &c0, &d0, &da, &db, &dc, &dd, &q);
	}
} op[350];

#define lowbit(x) (x&(-x))

int bit[M];

void add(int x, int v) {
	while (x <= n) {
		bit[x] += v;
		x += lowbit(x);
	}
}

int get(int x) {
	int ans = 0;
	while (x) {
		ans += bit[x];
		x -= lowbit(x);
	}
	return ans;
}

int get(int l, int r) {
	return get(r) - get(l - 1);
}

typedef pair<int, int> pii;
#define MP(a,b) make_pair(a,b)

map<pii, int> cnt;
int save[350];
ll mi7[350];

int main() {
	mi7[0] = 1;
	for (int i = 1; i < 350; i++)
		mi7[i] = mi7[i - 1] * 7 % MOD;
	while (~scanf("%d%d", &n, &m)) {
		cnt.clear();
		pn = 0;
		memset(bit, 0, sizeof(bit));
		int s0, t0, ds, dt, k;
		while (m--) {
			scanf("%d%d%d%d%d", &s0, &t0, &ds, &dt, &k);
			for (int i = 0; i < k; i++) {
				p[pn++] = Point(s0, t0, false);
				s0 = ((s0 + ds) % n + n) % n;
				t0 = ((t0 + dt) % n + n) % n;
			}
		}
		scanf("%d", &m);
		for (int i = 0; i < m; i++) {
			op[i].read();
			int a0 = op[i].a0, b0 = op[i].b0, c0 = op[i].c0, d0 = op[i].d0;
			int da = op[i].da, db = op[i].db, dc = op[i].dc, dd = op[i].dd;
			int q = op[i].q;
			for (int j = 0; j < q; j++) {
				int a = min(a0, b0), b = max(a0, b0), c = min(c0, d0), d = max(c0, d0);
				p[pn++] = Point(a - 1, c - 1, true);
				p[pn++] = Point(b, c - 1, true);
				p[pn++] = Point(a - 1, d, true);
				p[pn++] = Point(b, d, true);
				a0 = ((a0 + da) % n + n) % n;
				b0 = ((b0 + db) % n + n) % n;
				c0 = ((c0 + dc) % n + n) % n;
				d0 = ((d0 + dd) % n + n) % n;
			}
		}
		sort(p, p + pn, cmp);
		for (int i = 0; i < pn; i++) {
			if (p[i].isop) cnt[MP(p[i].x, p[i].y)] = get(1, p[i].x + 1);
			else add(p[i].x + 1, 1);
		}
		for (int i = 0; i < m; i++) {
			int a0 = op[i].a0, b0 = op[i].b0, c0 = op[i].c0, d0 = op[i].d0;
			int da = op[i].da, db = op[i].db, dc = op[i].dc, dd = op[i].dd;
			int q = op[i].q;
			for (int j = 0; j < q; j++) {
				int a = min(a0, b0), b = max(a0, b0), c = min(c0, d0), d = max(c0, d0);
				int tmp = cnt[MP(b, d)] - cnt[MP(a - 1, d)] - cnt[MP(b, c - 1)] + cnt[MP(a - 1, c - 1)];
				if (tmp == 0) save[j] = 0;
				else save[j] = 1;
				a0 = ((a0 + da) % n + n) % n;
				b0 = ((b0 + db) % n + n) % n;
				c0 = ((c0 + dc) % n + n) % n;
				d0 = ((d0 + dd) % n + n) % n;
			}
			if (q <= 20) {
				for (int j = 0; j < q; j++)
					printf("%d", save[j]);
				printf("\n");
			} else {
				ll out = 0;
				for (int j = 0; j < q; j++)
					out = (out + mi7[j] * save[j]) % MOD;
				printf("%lld\n", out);
			}
		}
	}
	return 0;
}

版权声明:本文博客原创文章。博客,未经同意,不得转载。

URAL 1707. Hypnotoad's Secret(树阵)

时间: 2024-10-12 03:48:48

URAL 1707. Hypnotoad&#39;s Secret(树阵)的相关文章

URAL 1707. Hypnotoad&#39;s Secret(树状数组)

URAL 1707. Hypnotoad's Secret 题目链接 题意:这题设置的恶心不能多说,构造点和矩形,大概就是问每个矩形里面是否包含点 思路:树状数组,把点排序,按y轴,在按x轴,在按询问,这样每次遇到一个点就在相应的扫描线上加,遇到查询就询问出左边到这个点位置的,就能预处理出每个点左下角包含的点的个数,然后每个矩形再利用容斥原理去搞一下即可 代码: #include <cstdio> #include <cstring> #include <algorithm&

ural 1707. Hypnotoad&#39;s Secret(线段树)

题目链接:ural 1707. Hypnotoad's Secret 题目大意:给定N和M,然后N组s0, t0, Δs, Δt, k,每组可以计算出k个星星的坐标:M组a0, b0, c0, d0, Δa, Δb, Δc, Δd, q,每组要求算出q个矩形,判断矩形内是否包含星星,对于q≥20的情况要根据公式计算一个值即可. 解题思路:计算出所有的星星坐标和矩阵,这个每的说了,将矩阵差分成两点,通过计算出每个点左下角有多少个星 星,然后用容斥计算出矩阵内是否有点.这个属于线段树的一个应用. #

URAL 1822. Hugo II&amp;#39;s War 树的结构+二分

1822. Hugo II's War Time limit: 0.5 second Memory limit: 64 MB The glorious King Hugo II has declared a war-a war that is holy, victorious, almost bloodless, but ruinous! Right after declaring the war the king has started summoning the army. He plans

URAL 1822. Hugo II&#39;s War 树的结构+二分

1822. Hugo II's War Time limit: 0.5 second Memory limit: 64 MB The glorious King Hugo II has declared a war-a war that is holy, victorious, almost bloodless, but ruinous! Right after declaring the war the king has started summoning the army. He plans

BZOJ 3211 弗洛拉前往国家 树阵+并检查集合

标题效果:给定一个序列,它提供了以下操作: 1.将[l.r]每个号码间隔a[i]变sqrt(a[i]) 2.查询[l,r]间隔和 剧烈的变化不支持由间隔,因此,我们选择单 - 点更换间隔查询的树阵,但是,这是O(n^2)的,怎么办? 我们发现一个数x最多开loglogx次根号就会变为1 也就是一个int范围内的数仅仅要开6次根号就会变为1 于是改动的总时间复杂度为O(nloglogn) 可是单次改动怎么办?我们维护一个并查集.一旦一个数为1或0,我们就把这个位置的father设为它右面的那个位置

HDOJ 5147 Sequence II 树阵

树阵: 每个号码的前面维修比其数数少,和大量的这后一种数比他的数字 再枚举每一个位置组合一下 Sequence II Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 121    Accepted Submission(s): 58 Problem Description Long long ago, there is a sequen

URAL 1439. Battle with You-Know-Who treap树

题目来源:URAL 1439. Battle with You-Know-Who 题意:开始有数列1, 2, 3, ... L k输出第k大的数 D k删除第k大的数 思路:treap树插入删除的数 每次二分查找第k大的数为mid 查询treap小于等于mid的数有y个 那么mid应该是第mid-y大的数 与k比较 继续二分 #include <cstdio> #include <cstring> #include <cstdlib> #include <algo

URAL 1727. Znaika&amp;#39;s Magic Numbers(数学 vector)

主题链接:http://acm.timus.ru/problem.aspx?space=1&num=1727 1727. Znaika's Magic Numbers Time limit: 0.5 second Memory limit: 64 MB Znaika has many interests. For example, now he is investigating the properties of number sets. Znaika writes down some set

BZOJ 3594 Scoi2014 方波波麦田 树阵

标题效果:给定一个序列,能够选择k次每个部分的数量和在范围内+1,寻求操作后LIS最大值 我的做法是不是一个标准的解决方案. ..5E为什么跑飞的复杂性. . . 首先,显而易见的结论是,我们选择k右端点都是n时才干保证最优 知道这个我们就能够DP了- - 令f[i][j]表示前i个数上升j次的最大LIS 那么有f[i][j]=max{f[k][l]|k<i,l<=j,a[k]+l<=a[i]+j}+1 看到三维偏序就能够用二维树状数组了- - 时间复杂度O(nklog(max(ai)+