标签:lower date main cto bsp cst 持久 枚举 竖线
区间修改:
修改l到r之间的值 , 遍历线段树 , 若某个子节点l<=L && R<=r ,
则在该节点上标记修改的值 , 访问该节点及他的子节点时再将标记下传;
每当修改值的时候 , 新建一个跟节点 , 将他与上一个版本的线段树中未修改的值相连 ,
对于修改的值新建一个节点 , 当访问到新节点及他的子节点时再动态开点;
int t[N*2];
for(int i=1;i<=n;i++) t[i+N]=a[i];
t[x+=N]=y;
for(x>>=1;x;x>>=1)
{
t[x]=t[x<<1]+t[x<<1|1];
}
int ans=0;
for(l+=N-1,r+=N;l^r^1;l>>=1,r>>=1) // l^r^1用来判断左右节点的父节点是不是同一个节点
{
/* 如果当前区间的左端点在他父节点的左子节点上就要加上他的父节点的右子节点,
相当于左端点包括了右字节点所包括的数*/
if(!(l^1)) ans+=t[l^1];
/* 如果当前区间的右端点在他父节点的右子节点上就要加上他的父节点的左子节点*/
if(r^1) ans+=t[r^1];
}
不能标记下传;
可以用来代替堆优化Dijkstra;
建立一棵范围为[1,n]的线段树,再在这棵线段树的每个节点上建立一棵范围为[1,m]的线段树;
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 8 const int N = 100010; 9 10 int n; 11 int a[9]; 12 int cntx, cnty; 13 int x[N], y[N]; 14 int sum[N * 20], ls[N * 20], rs[N * 20], root[N], tot; 15 vector<int> ins[N]; 16 17 struct Node 18 { 19 int x, y; 20 }t[N]; 21 22 void update(int& q, int last, int l, int r, int v) 23 { 24 q = ++tot; 25 ls[q] = ls[last]; 26 rs[q] = rs[last]; 27 sum[q] = sum[last] + 1; 28 29 if(l == r) return; 30 int mid = (l + r) >> 1; 31 if (v <= mid) update(ls[q], ls[last], l, mid, v); 32 else update(rs[q], rs[last], mid + 1, r, v); 33 } 34 35 int kth(int p, int q, int l, int r, int v) // 找第p版本线段树到第q版本线段树中差值为v的节点 36 { 37 if (l == r) return l; 38 39 int s = sum[ls[q]] - sum[ls[p]]; 40 int mid = (l + r) >> 1; 41 if (s >= v) return kth(ls[p], ls[q], l, mid, v); 42 else return kth(rs[p], rs[q], mid + 1, r, v - s); 43 } 44 45 int query(int q, int l, int r, int L, int R) // 求区间和 46 { 47 if ((!q) || (L <= l && r <= R)) return sum[q]; 48 49 int res = 0; 50 int mid = (l + r) >> 1; 51 if (L <= mid) res += query(ls[q], l, mid, L, R); 52 if (R > mid) res += query(rs[q], mid + 1, r, L, R); 53 return res; 54 } 55 56 57 int S(int l1, int r1, int l2, int r2) // 求子矩阵 点[l1,l2] 到 点[r1,r2] 之间的点的数量 58 { 59 return query(root[r1], 1, cnty, l2, r2) - query(root[l1 - 1], 1, cnty, l2, r2); 60 } 61 62 bool solve() 63 { 64 int l = 1, r = cntx, ans = 0; // 求在左边的那条竖线 65 while (l <= r) 66 { 67 int mid = (l + r) >> 1; 68 if (sum[root[mid]] >= a[0] + a[1] + a[2]) 69 { 70 ans = mid; 71 r = mid - 1; 72 } 73 else l = mid + 1; 74 } 75 if (ans == 0 || sum[root[ans]] != a[0] + a[1] + a[2]) return false; // 没找到这条线 76 int p1 = ans; 77 78 l = 1, r = cntx, ans = 0; // 求在右边的那条竖线 79 while (l <= r) 80 { 81 int mid = (l + r) >> 1; 82 if (sum[root[mid]] >= a[0] + a[1] + a[2] + a[3] + a[4] + a[5]) 83 { 84 ans = mid; 85 r = mid - 1; 86 } 87 else l = mid + 1; 88 } 89 if (ans == 0 || sum[root[ans]] != a[0] + a[1] + a[2] + a[3] + a[4] + a[5]) return false; // 没找到这条线 90 int p2 = ans; 91 92 int posx1 = kth(root[0], root[p1], 1, cnty, a[0]); // 找上面那条横线 93 while (S(1, p1, 1, posx1) != a[0] || S(p1 + 1, p2, 1, posx1) != a[3] || S(p2 + 1, cntx, 1, posx1) != a[6]) 94 { 95 if (S(1, p1, 1, posx1) != a[0]) return false; // 找不到 96 ++posx1; 97 } 98 99 int posx2 = kth(root[0], root[p1], 1, cnty, a[0] + a[1]); // 找下面那条横线 100 while (S(1, p1, posx1+1, posx2) != a[1] || S(p1 + 1, p2, posx1 + 1, posx2) != a[4] || S(p2 + 1, cntx, posx1 + 1, posx2) != a[7]) 101 { 102 if (S(1, p1, posx1 + 1, posx2) != a[1]) return false; // 找不到 103 ++posx2; 104 } 105 106 printf("%.10lf %.10lf \n%.10lf %.10lf", x[p1] + 0.5, x[p2] + 0.5, y[posx1] + 0.5, y[posx2] + 0.5); 107 return true; 108 } 109 110 bool com(Node a, Node b) 111 { 112 return a.x == b.x ? a.y < b.y : a.x < b.x; 113 } 114 115 int main() 116 { 117 scanf("%d", &n); 118 for (int i = 1; i <= n; i++) 119 { 120 scanf("%d%d", &t[i].x, &t[i].y); 121 x[++cntx] = t[i].x; 122 y[++cnty] = t[i].y; 123 } 124 for (int i = 0; i < 9; i++) scanf("%d", &a[i]); 125 126 sort(x + 1, x + 1 + cntx); 127 cntx = unique(x + 1, x + 1 + cntx) - (x + 1); 128 sort(y + 1, y + 1 + cnty); 129 cnty = unique(y + 1, y + 1 + cnty) - (y + 1); 130 sort(t + 1, t + 1 + n, com); 131 132 for (int i = 1; i <= n; i++) // 哈希 133 { 134 t[i].x = lower_bound(x + 1, x + cntx + 1, t[i].x) - x; 135 t[i].y = lower_bound(y + 1, y + cnty + 1, t[i].y) - y; 136 ins[t[i].x].push_back(t[i].y); 137 } 138 139 for (int i = 1; i <= cntx; i++) // 建可持久化线段树 140 { 141 root[i] = root[i - 1]; 142 for (int j = 0; j < ins[i].size(); j++) 143 { 144 update(root[i], root[i], 1, cnty, ins[i][j]); 145 } 146 } 147 148 int loop = 362880; 149 while (loop--) 150 { 151 next_permutation(a, a + 9); // 全排列 152 if (solve()) return 0; 153 } 154 155 puts("-1"); 156 }
标签:lower date main cto bsp cst 持久 枚举 竖线
原文地址:https://www.cnblogs.com/Arrogant-Hierarch/p/13210751.html