题意:对于点集S,定义函数F(S)为对S不断扩展到不能扩展时S的点数。一次扩展定义为如果有一个平行于坐标轴的矩形的三个点在S中,则第四个点加入S。

动态在S中加点删点,每次操作完后求F(S)的值。

解:首先有个结论就是,把这些点用平行于坐标轴的线段连接起来,则E值为每个连通块的横坐标种数 * 纵坐标种数之和。

线段树分治 + 可回退化并查集,O(nlog2n)。

 #include <bits/stdc++.h>

 typedef long long LL;
const int N = ; struct Node {
int x, y;
Node(int X, int Y) {
x = X;
y = Y;
}
}; std::map<int, int> mp[N];
int n, m;
LL ans[N];
std::vector<Node> v[N << ]; namespace ufs { struct opt {
int x, y;
opt(){}
opt(int X, int Y) {
x = X, y = Y;
}
}stk[N * ]; int top; int fa[N * ], siz[N * ], s1[N * ], s2[N * ], clock;
LL tot, stk2[N];
inline void init() {
for(int i = ; i < N; i++) {
fa[i] = i;
fa[i + N] = i + N;
siz[i] = siz[i + N] = ;
s1[i] = s2[i + N] = ;
s2[i] = s1[i + N] = ;
}
top = clock = ;
return;
}
int find(int x) {
if(x == fa[x]) return x;
return find(fa[x]);
}
inline LL cal(int x) {
return 1ll * s1[x] * s2[x];
}
inline void merge(int x, int y) {
x = find(x);
y = find(y);
if(x == y) return;
if(siz[x] < siz[y]) {
std::swap(x, y);
}
stk2[++clock] = tot;
tot -= cal(x) + cal(y);
stk[++top] = opt(y, fa[y]);
fa[y] = x;
stk[++top] = opt(x, siz[x]);
siz[x] += siz[y];
stk[++top] = opt(x, s1[x]);
s1[x] += s1[y];
stk[++top] = opt(x, s2[x]);
s2[x] += s2[y];
tot += cal(x);
return;
}
inline void erase(int t) {
while(clock > t) {
tot = stk2[clock--];
s2[stk[top].x] = stk[top].y;
top--;
s1[stk[top].x] = stk[top].y;
top--;
siz[stk[top].x] = stk[top].y;
top--;
fa[stk[top].x] = stk[top].y;
top--;
}
return;
}
} void add(int L, int R, Node x, int l, int r, int o) {
if(L <= l && r <= R) {
v[o].push_back(x);
return;
}
int mid = (l + r) >> ;
if(L <= mid) {
add(L, R, x, l, mid, o << );
}
if(mid < R) {
add(L, R, x, mid + , r, o << | );
}
return;
} void solve(int l, int r, int o) {
int now = ufs::clock;
for(int i = ; i < (int)v[o].size(); i++) {
ufs::merge(v[o][i].x, v[o][i].y + N);
//printf("[%d %d] merge %d %d \n", l, r, v[o][i].x, v[o][i].y);
}
if(l == r) {
ans[r] = ufs::tot;
ufs::erase(now);
return;
}
int mid = (l + r) >> ;
solve(l, mid, o << );
solve(mid + , r, o << | );
ufs::erase(now);
return;
} int main() {
ufs::init();
scanf("%d", &n);
for(int i = , x, y; i <= n; i++) {
scanf("%d%d", &x, &y);
if(mp[x][y]) {
add(mp[x][y], i - , Node(x, y), , n, );
//printf("add : (%d %d) [%d %d] \n", x, y, mp[x][y], i - 1);
mp[x][y] = ;
}
else {
mp[x][y] = i;
}
}
std::map<int, int>::iterator it;
for(int i = ; i < N; i++) {
for(it = mp[i].begin(); it != mp[i].end(); it++) {
if(it->second) {
add(it->second, n, Node(i, it->first), , n, );
//printf("add : (%d %d) [%d %d] \n", i, it->first, it->second, n);
}
}
} solve(, n, );
for(int i = ; i <= n; i++) {
printf("%lld ", ans[i]);
}
return ;
}

AC代码

最新文章

  1. 不容错过!2016年度优秀UI/UX设计文章
  2. Atitit Server Side Include &#160;ssi服务端包含规范&#160;csi &#160;esi
  3. JSBinding + SharpKit / 常见问题
  4. ExtJs之工具栏及菜单栏
  5. c++builder CryptoAPI md5
  6. POJ 1740
  7. mac os x 10.9.1 安装 Homebrew软件包管理工具及brew安装maven3.1.1
  8. Impala 源码分析-FE
  9. Apache的最小配置
  10. 使用Pushlet将消息从服务器端推送到客户端
  11. JAVA基础——内部类详解
  12. centos7系统优化定制
  13. VMware虚拟机Mac OS X无法调整扩展硬盘大小的解决方案(转)
  14. BZOJ.1901.Dynamic Rankings(线段树套平衡树 Splay)
  15. [math] 绘制空间几何体的直观图
  16. Java综合高级篇
  17. Thinkphp框架下设置session的过期时间
  18. 使用python+selenium对web进行自动化测试
  19. Delphi中使一个窗口居中
  20. ScrollView嵌套ListView只显示一行之计算的高度不正确的解决办法(转)

热门文章

  1. scala中异常捕获与处理简单使用
  2. 长链接生成短链接Java源码(调用百度接口)
  3. thinkphp switch标签
  4. 2019/11/1 CSP模拟
  5. 关于Ubuntu锁屏后,无法输入密码
  6. Spring MVC(十六)--Spring MVC国际化实例
  7. idea在同一窗口创建多个项目(详细步骤)
  8. java_增强for循环
  9. PropertyPlaceholderConfigurer的注意事项
  10. CVE-2016-0095提权漏洞分析