ural 1707. Hypnotoad's Secret(线段树)

2024-06-05 01:58

本文主要是介绍ural 1707. Hypnotoad'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的情况要根据公式计算一个值即可。

解题思路:计算出所有的星星坐标和矩阵,这个每的说了,将矩阵差分成两点,通过计算出每个点左下角有多少个星

星,然后用容斥计算出矩阵内是否有点。这个属于线段树的一个应用。

#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>using namespace std;
typedef long long ll;const ll mod = 200904040963LL;
const int maxn = 300000;#define lson(x) ((x)<<1)
#define rson(x) (((x)<<1)|1)
int lc[maxn << 2], rc[maxn << 2], s[maxn << 2];inline void pushup(int u) {s[u] = s[lson(u)] + s[rson(u)];
}void build (int u, int l, int r) {lc[u] = l;rc[u] = r;s[u] = 0;if (l == r)return;int mid = (l + r) / 2;build(lson(u), l, mid);build(rson(u), mid + 1, r);pushup(u);
}void modify(int u, int x) {if (lc[u] == x && x == rc[u]) {s[u] += 1;return;}int mid = (lc[u] + rc[u]) / 2;if (x <= mid)modify(lson(u), x);elsemodify(rson(u), x);pushup(u);
}int query(int u, int l, int r) {if (l <= lc[u] && rc[u] <= r)return s[u];int mid = (lc[u] + rc[u]) / 2, ret = 0;if (l <= mid)ret += query(lson(u), l, r);if (r > mid)ret += query(rson(u), l, r);return ret;
}struct point {int t,  x, y;point (int x = 0, int y = 0, int t = 0) {set(x, y);this->t = t;}void set (int x, int y) {this->x = x;this->y = y;}friend bool operator < (const point& a, const point& b) {if (a.x != b.x)return a.x < b.x;if (a.y != b.y)return a.y < b.y;return a.t < b.t;}
};struct state {point a, b;state (point a, point b) {this->a = a;this->b = b;}
};int N, M, P;
ll T[350];
vector<int> pos, tmp, cnt;
vector<point> vec;
vector<state> que;
map<point, int> G;inline void add_point (ll x, ll y, int k) {vec.push_back(point(x, y, k));tmp.push_back(y);
}inline void add_state (int a, int b, int c, int d) {add_point(a - 1, b - 1, 1);add_point(c, d, 1);int u = vec.size();que.push_back(state(vec[u-2], vec[u-1]));add_point(a - 1, d, 1);add_point(c, b - 1, 1);
}inline int find (int a) {return lower_bound(pos.begin(), pos.end(), a) - pos.begin();
}void init () {G.clear();cnt.clear();vec.clear();que.clear();pos.clear();tmp.clear();int a, b, c, d, aa, bb, cc, dd, k;for (int i = 0; i < M; i++) {scanf("%d%d%d%d%d", &a, &b, &aa, &bb, &k);a = (a + N) % N; b = (b + N) % N;for (int j = 0; j < k; j++) {add_point(a, b, 0);a = (a + aa + N) % N;b = (b + bb + N) % N;}}scanf("%d", &P);for (int i = 0; i < P; i++) {scanf("%d%d%d%d", &a, &b, &c, &d);scanf("%d%d%d%d%d", &aa, &bb, &cc, &dd, &k);a = (a + N) % N; b = (b + N) % N;c = (c + N) % N; d = (d + N) % N;cnt.push_back(k);for (int j = 0; j < k; j++) {add_state(min(a, b), min(c, d), max(a, b), max(c, d));a = (a + aa + N) % N; b = (b + bb + N) % N;c = (c + cc + N) % N; d = (d + dd + N) % N;}}sort(vec.begin(), vec.end());sort(tmp.begin(), tmp.end());pos.push_back(tmp[0]);for (int i = 1; i < tmp.size(); i++) {if (tmp[i] != tmp[i-1])pos.push_back(tmp[i]);}build(1, 0, pos.size());
}inline int judge (state u) {return G[u.b] + G[u.a] - G[point(u.b.x, u.a.y, 1)] - G[point(u.a.x, u.b.y, 1)];
}void solve () {for (int i = 0; i < vec.size(); i++) {if (vec[i].t)G[vec[i]] = query(1, 0, find(vec[i].y));elsemodify(1, find(vec[i].y));}int mv = 0;for (int i = 0; i < cnt.size(); i++) {if (cnt[i] > 20) {ll ret = 0;for (int j = 0; j < cnt[i]; j++)ret = (ret + (judge(que[mv + j]) > 0 ? 1 : 0) * T[j]) % mod;printf("%lld", ret);} else {for (int j = 0; j < cnt[i]; j++)printf("%d", judge(que[mv + j]) > 0 ? 1 : 0);}mv += cnt[i];printf("\n");}
}int main () {T[0] = 1;for (int i = 1; i <= 345; i++)T[i] = T[i-1] * 7 % mod;while (scanf("%d%d", &N, &M) == 2) {init();solve();}return 0;
}

这篇关于ural 1707. Hypnotoad's Secret(线段树)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1031748

相关文章

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

90、k8s之secret+configMap

一、secret配置管理 配置管理: 加密配置:保存密码,token,其他敏感信息的k8s资源 应用配置:我们需要定制化的给应用进行配置,我们需要把定制好的配置文件同步到pod当中容器 1.1、加密配置: secret: [root@master01 ~]# kubectl get secrets ##查看加密配置[root@master01 ~]# kubectl get se

poj 1127 线段相交的判定

题意: 有n根木棍,每根的端点坐标分别是 px, py, qx, qy。 判断每对木棍是否相连,当他们之间有公共点时,就认为他们相连。 并且通过相连的木棍相连的木棍也是相连的。 解析: 线段相交的判定。 首先,模板中的线段相交是不判端点的,所以要加一个端点在直线上的判定; 然后,端点在直线上的判定这个函数是不判定两个端点是同一个端点的情况的,所以要加是否端点相等的判断。 最后

HDU4737线段树

题目大意:给定一系列数,F(i,j)表示对从ai到aj连续求或运算,(i<=j)求F(i,j)<=m的总数。 const int Max_N = 100008 ;int sum[Max_N<<2] , x[Max_N] ;int n , m ;void push_up(int t){sum[t] = sum[t<<1] | sum[t<<1|1] ;}void upd

zoj 1721 判断2条线段(完全)相交

给出起点,终点,与一些障碍线段。 求起点到终点的最短路。 枚举2点的距离,然后最短路。 2点可达条件:没有线段与这2点所构成的线段(完全)相交。 const double eps = 1e-8 ;double add(double x , double y){if(fabs(x+y) < eps*(fabs(x) + fabs(y))) return 0 ;return x + y ;

圆与线段的交点

poj 3819  给出一条线段的两个端点,再给出n个圆,求出这条线段被所有圆覆盖的部分占了整条线段的百分比。 圆与线段的交点 : 向量AB 的参数方程  P = A + t * (B - A)      0<=t<=1 ; 将点带入圆的方程即可。  注意: 有交点 0 <= t <= 1 ; 此题求覆盖的部分。 则 若求得 t  满足 ; double ask(d