http://47.92.197.167:5283/contest/454/problem/2
暴力思路,也就是我们要维护的是。从上一行过来的时候,找到第一个不能继续保持1的位置,在它前面找到第一个可以从0变成1的位置变成1,然后把那个位置后面全部清空。
我们现在要实现的是什么:
假设我们能够做。每次只会加入1,所以直接暴力清空3.中的是没问题的。
对于2.,我们如果直接找下一个任意位置,可能现在已经是1了,但这无所谓,我们就继续找。而刚刚那个位置未来肯定会被删掉,所以复杂度也是对的。
对于1.,我们感觉很难处理。此时我们可以考虑按列维护,维护当前选了的每一列什么时候挂掉。
开一堆set来搞。
#include
using namespace std;
#ifdef LOCAL
#define debug(...) fprintf(stdout, ##__VA_ARGS__)
#else
#define debug(...) void(0)
#endif
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
#define Z(x) (x)*(x)
#define pb push_back
#define fi first
#define se second
//#define M
#define mo (int)(1e9 + 7)
#define N 1010
int Pow2(int b) {
int ans = 1, a = 2;
while(b) {
if(b & 1) ans *= a;
a *= a; b >>= 1;
ans %= mo; a %= mo;
}
return ans;
}
void Mod(int &a) { if(a <= -mo || a >= mo) a %= mo; if(a < 0) a += mo; }
struct node {
int x, l, r;
bool operator < (const node &A) const {
if(x == A.x) {
if(l == A.l) return r < A.r;
return l < A.l;
}
return x < A.x;
}
};
multiset<node>S;
struct Node {
int x, t;
bool operator < (const Node &A) const {
if(t == A.t) return x < A.x;
return t < A.t;
}
};
multiset<Node>s2;
multiset<int>s[N], s1;
int n, m, i, j, k, T, q, ans, sum, op, mx;
int qtm(int i, int j) {
auto it = S.lower_bound({i, j, j});
// debug("I find it [%lld [%lld %lld]]\n", (*it).x, (*it).l, (*it).r);
if(it != S.end() && (it -> x) == i && (it -> l) == j) return it -> r;
else return --it, (it -> r);
}
void add(int i, int j) {
assert(s1.find(j) == s1.end());
// debug("Insert %lld\n", j);
s1.insert(j); sum += Pow2(j); Mod(sum);
int t = qtm(j, i);
// debug("qtm[%lld in %lld] is %lld || %lld\n", j, i, t, s2.size());
// for(auto t: s2) debug("== %lld %lld\n", t.x, t.t);
assert(s2.find({j, t}) == s2.end());
s2.insert({j, t});
}
void del(int j, int et) {
// debug("Erase %lld\n", j);
sum -= Pow2(j); Mod(sum);
assert(s1.find(j) != s1.end());
s1.erase(j);
assert(s2.find({j, et}) != s2.end());
s2.erase({j, et});
}
signed main()
{
// #ifdef LOCAL
freopen("price.in", "r", stdin);
freopen("price.out", "w", stdout);
// #endif
// srand(time(NULL));
// T=read();
// while(T--) {
//
// }
n = read(); m = read(); q = read();
while(q--) {
op = read();
if(op == 1) {
i = read(); j = m - read();
if(s[i].find(j) != s[i].end()) s[i].erase(j);
else s[i].insert(j);
if(S.empty()) S.insert({j, i, i});
else {
auto it = S.lower_bound({j, i, i});
if(it != S.end() && (it -> l) == i && (it -> x) == j) {
if((it -> l) == (it -> r)) S.erase(it);
else S.insert({j, i + 1, (it -> r)}), S.erase(it);
}
else {
// debug("At(%lld %lld) (%lld)[%lld %lld]\n", i, j, (*it).x, (*it).l, (*it).r);
if(it != S.begin()) --it;
if((it -> x) == j && (it -> l) <= i && (it -> r) >= i) {
if(i != (it -> l)) S.insert({j, (it -> l), i - 1});
if(i != (it -> r)) S.insert({j, i + 1, (it -> r)});
S.erase(it);
}
else {
int L = i, R = i;
if((it -> x) == j && (it -> r) == i - 1) {
L = (it -> l); auto it1 = it; ++it;
S.erase(it1);
}
else if((it -> x) == j && (it -> l) == i + 1) {
R = (it -> r); auto it1 = it; ++it;
S.erase(it1);
}
else ++it;
if(it != S.end() && (it -> x) == j && (it -> l) == i + 1) {
R = (it -> r); S.erase(it);
}
S.insert({j, L, R});
}
}
}
// for(auto t : S) debug("%lld [%lld %lld]\n", t.x, t.l, t.r);
// debug("---\n");
}
else {
// for(auto t : S) debug("%lld [%lld %lld]\n", t.x, t.l, t.r);
s1.clear(); s2.clear(); sum = ans = 0;
if(s[1].empty()) { printf("-1\n"); continue; }
auto it = s[1].begin();
add(1, *it); ans += sum; Mod(ans);
// debug("<1> [%lld]%lld\n", *it, sum);
for(i = 2; i <= n; ++i) {
mx = -1;
assert(s1.size() == s2.size());
while(!s2.empty() && (*s2.begin()).t < i) {
auto t = (*s2.begin());
mx = max(mx, t.x);
// debug("I make a delete\n");
del(t.x, t.t);
}
auto it = s[i].upper_bound(mx);
// debug("<%lld> mx %lld *it %lld | sum %lld || %lld\n", i, mx, *it, sum, (*s2.begin()).t);
int flg = 0;
if(it == s[i].end()) break;
while(s1.find(*it) != s1.end()) {
mx = (*it);
it = s[i].upper_bound(mx);
if(it == s[i].end()) { flg = 1; break; }
}
if(flg) break;
mx = (*it);
// debug("lst mx : %lld\n", mx);
while(!s1.empty() && (*s1.begin()) < mx) {
int k = (*s1.begin());
del(k, qtm(k, i));
}
add(i, mx);
// debug("[%lld]>> %lld\n", i, sum);
ans += sum; Mod(ans);
}
if(i <= n) { printf("-1\n"); continue; }
printf("%lld\n", ans);
}
}
return 0;
}