bzoj1106: [POI2007]立方体大作战tet

HomuraCat

2019-04-24 18:29:26

Personal

[题链](https://www.lydsy.com/JudgeOnline/problem.php?id=1106) 首先这道题我们很容易想到要贪心考虑一对数对$(l,r)$使得在这个区间中没有两两匹配的情况 然后这两个数的贡献就是$r-l-1$,然后我们就可以把它们两个删掉了。 显然这个贪心是对的,因为我们并没有改变其它数的相对位置,并且这两个数也没有更快的方法被消除(因为它们中间原本不可能被清除) 但是显然这个贪心是$O(n^2)$的,考虑优化 直接用树状数组维护就行了啦没多难的 瞟一眼代码你就懂了懒得写 ````cpp #include<bits/stdc++.h> #define Re register #define fo(i, a, b) for (int i = (a); i <= (b); ++i) #define fd(i, a, b) for (int i = (a); i >= (b); --i) #define edge(i, u) for (Re int i = head[u], v = e[i].v; i; i = e[i].nxt, v = e[i].v) #define pb push_back #define F first #define S second #define ll long long #define inf 1000000007 #define mp std::make_pair //#define mod 1000000007 #define eps 1e-4 #define lowbit(x) (x & -x) #define N 100005 #define ls (u << 1) #define rs (u << 1 | 1) #define cl(arr) memset(arr, 0, sizeof arr) inline void read (int &x) { x = 0; Re char ch = getchar(); while (!isdigit(ch)) ch = getchar(); while (isdigit(ch)) x = (x << 3) + (x << 1) + ch - '0', ch = getchar(); } int n, a[N], l[N], r[N]; bool vis[N]; int t[N], ans; inline void add (int x, int v) { for (int i = x; i <= n; i += lowbit(i)) t[i] += v; } inline int query (int x) { int ret = 0; for (int i = x; i; i -= lowbit(i)) ret += t[i]; return ret; } int main () { read(n); n = n << 1; fo (i, 1, n) { read(a[i]); if (vis[a[i]]) r[a[i]] = i; else l[a[i]] = i, vis[a[i]] = 1; } fo (i, 1, n) { if (l[a[i]] == i) add(i, 1); else { ans += query(i) - query(l[a[i]]); add(l[a[i]], -1); } } printf("%d", ans); return 0; } ```