QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#614265 | #9449. New School Term | ucup-team5071# | TL | 786ms | 19264kb | C++20 | 9.7kb | 2024-10-05 16:02:47 | 2024-10-05 16:02:48 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5, P = 998244353;
typedef array<int,2> info;
int f[maxn];
info siz[maxn];
#define fp(i, a, b) for (int i = (a), i##_ = (b) + 1; i < i##_; ++i)
#define fd(i, a, b) for (int i = (a), i##_ = (b) - 1; i > i##_; --i)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
using namespace std;
using arr = int[maxn];
using ll = int64_t;
/*---------------------------------------------------------------------------*/
class Cipolla {
int P, I2{};
using pll = pair<ll, ll>;
#define X first
#define Y second
ll mul(ll a, ll b) const { return a * b % P; }
pll mul(pll a, pll b) const { return {(a.X * b.X + I2 * a.Y % P * b.Y) % P, (a.X * b.Y + a.Y * b.X) % P}; }
template<class T> T POW(T a, int b, T x) { for (; b; b >>= 1, a = mul(a, a)) if (b & 1) x = mul(x, a); return x; }
public:
Cipolla(int p = 0) : P(p) {}
pair<int, int> sqrt(int n) {
int a = rand(), x;
if (!(n %= P))return {0, 0};
if (POW(n, (P - 1) >> 1, (int)1) == P - 1) return {-1, -1};
while (POW(I2 = ((ll) a * a - n + P) % P, (P - 1) >> 1, (int)1) == 1) a = rand();
x = (int) POW(pll{a, 1}, (P + 1) >> 1, {1, 0}).X;
if (2 * x > P) x = P - x;
return {x, P - x};
}
#undef X
#undef Y
};
/*---------------------------------------------------------------------------*/
#define ADD(a, b) (((a) += (b)) >= P ? (a) -=P : 0) // (a += b) %= P
#define SUB(a, b) (((a) -= (b)) < 0 ? (a) += P: 0) // ((a -= b) += P) %= P
#define MUL(a, b) ((ll) (a) * (b) % P)
//vector<int> getInv(int L) {
// vector<int> inv(L); inv[1] = 1;
// fp(i, 1, L - 1) inv[i] = MUL((P - P / i), inv[P % i]);
// return inv;
//}
//auto inv = getInv(maxn); // NOLINT
int POW(ll a, int b = P - 2, ll x = 1) { for (; b; b >>= 1, a = a * a % P) if (b & 1) x = x * a % P; return x; }
//int INV(int a) { return a < maxn ? inv[a] : POW(a); }
namespace NTT {
const int g = 3;
vector<int> Omega(int L) {
int wn = POW(g, P / L);
vector<int> w(L); w[L >> 1] = 1;
fp(i, L / 2 + 1, L - 1) w[i] = MUL(w[i - 1], wn);
fd(i, L / 2 - 1, 1) w[i] = w[i << 1];
return w;
}
auto W = Omega(1 << 21); // NOLINT
void DIF(int *a, int n) {
for (int k = n >> 1; k; k >>= 1)
for (int i = 0, y; i < n; i += k << 1)
fp(j, 0, k - 1)
y = a[i + j + k], a[i + j + k] = MUL(a[i + j] - y + P, W[k + j]), ADD(a[i + j], y);
}
void IDIT(int *a, int n) {
for (int k = 1; k < n; k <<= 1)
for (int i = 0, x, y; i < n; i += k << 1)
fp(j, 0, k - 1)
x = a[i + j], y = MUL(a[i + j + k], W[k + j]),
a[i + j + k] = x - y < 0 ? x - y + P : x - y, ADD(a[i + j], y);
int Inv = P - (P - 1) / n;
fp(i, 0, n - 1) a[i] = MUL(a[i], Inv);
reverse(a + 1, a + n);
}
}
namespace Polynomial {
using Poly = std::vector<int>;
// mul/div int
Poly &operator*=(Poly &a, int b) { for (auto &x : a) x = MUL(x, b); return a; }
Poly operator*(Poly a, int b) { return a *= b; }
Poly operator*(int a, Poly b) { return b * a; }
Poly &operator/=(Poly &a, int b) { return a *= POW(b); }
Poly operator/(Poly a, int b) { return a /= b; }
// Poly add/sub
Poly &operator+=(Poly &a, Poly b) {
a.resize(max(a.size(), b.size()));
fp(i, 0, b.size() - 1) ADD(a[i], b[i]);
return a;
}
Poly operator+(Poly a, Poly b) { return a += b; }
Poly &operator-=(Poly &a, Poly b) {
a.resize(max(a.size(), b.size()));
fp(i, 0, b.size() - 1) SUB(a[i], b[i]);
return a;
}
Poly operator-(Poly a, Poly b) { return a -= b; }
// Poly mul
void DFT(Poly &a) { NTT::DIF(a.data(), a.size()); }
void IDFT(Poly &a) { NTT::IDIT(a.data(), a.size()); }
int norm(int n) { return 1 << (32 - __builtin_clz(n - 1)); }
void norm(Poly &a) { if (!a.empty()) a.resize(norm(a.size()), 0); }
Poly &dot(Poly &a, Poly &b) {
fp(i, 0, a.size() - 1) a[i] = MUL(a[i], b[i]);
return a;
}
Poly operator*(Poly a, Poly b) {
int n = a.size() + b.size() - 1, L = norm(n);
if (a.size() <= 8 || b.size() <= 8) {
Poly c(n);
fp(i, 0, a.size() - 1) fp(j, 0, b.size() - 1)
c[i + j] = (c[i + j] + (ll) a[i] * b[j]) % P;
return c;
}
a.resize(L), b.resize(L);
DFT(a), DFT(b), dot(a, b), IDFT(a);
return a.resize(n), a;
}
// Poly inv
Poly Inv2k(Poly a) { // a.size() = 2^k
int n = a.size(), m = n >> 1;
if (n == 1) return {POW(a[0])};
Poly b = Inv2k(Poly(a.begin(), a.begin() + m)), c = b;
b.resize(n), DFT(a), DFT(b), dot(a, b), IDFT(a);
fp(i, 0, n - 1) a[i] = i < m ? 0 : P - a[i];
DFT(a), dot(a, b), IDFT(a);
return move(c.begin(), c.end(), a.begin()), a;
}
Poly Inv(Poly a) {
int n = a.size();
norm(a), a = Inv2k(a);
return a.resize(n), a;
}
// Poly div/mod
Poly operator/(Poly a,Poly b){
int k = a.size() - b.size() + 1;
if (k < 0) return {0};
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
b.resize(k), a = a * Inv(b);
a.resize(k), reverse(a.begin(), a.end());
return a;
}
pair<Poly, Poly> operator%(Poly a, const Poly& b) {
Poly c = a / b;
a -= b * c, a.resize(b.size() - 1);
return {c, a};
}
// Poly sqrt
Poly Sqrt(Poly a) {
int n = a.size(), k = norm(n);
Poly b = {(new Cipolla(P))->sqrt(a[0]).first}, c;
a.resize(k * 2, 0);
for (int L = 2; L <= k; L <<= 1) {
b.resize(2 * L, 0), c = Poly(a.begin(), a.begin() + L) * Inv(b);
fp(i, 0, 2 * L - 1) b[i] = MUL(b[i] + c[i], (P + 1) / 2);
}
return b.resize(n), b;
}
// Poly calculus
void Derivative(Poly &a) {
fp(i, 1, a.size() - 1) a[i - 1] = MUL(i, a[i]);
a.pop_back();
}
}
using namespace Polynomial;
int n,m;
int getf(int x){
if(x<0)return -getf(-x);
if(x==f[x])return x;
else return f[x]=getf(f[x]);
}
multiset<info> s;
bool check()
{
int siz=s.size();
vector<Poly> all;
for(auto [x,y]:s){
Poly a(max(x,y)+1);
a[x]++,a[y]++;
all.push_back(a);
}
for(int j=0;j<15;j++){
for(int i=0;i+(1<<j)<siz;i+=(1<<(j+1)))all[i]=all[i]*all[i+(1<<j)];
}
// cout<<"check = "<<endl;
// for(auto [x,y]:s)cout<<x<<"/"<<y<<" ";;cout<<endl;
// cout<<all[0][n]<<endl;
return all[0][n]>0;
}
bool merge(int x,int y){//如果是x!=y将y取反(x>0 y>0)
if(getf(x)==-getf(y))return false;
if(getf(x)==getf(y))return true;
x=getf(x),y=getf(y);
if(x<0)x=-x,y=-y;
if(siz[x][0]+(y>0?siz[y][0]:siz[-y][1])>n)return false;
if(siz[x][1]+(y>0?siz[y][1]:siz[-y][0])>n)return false;
// cout<<"merge x="<<x<<" y="<<y<<" s="<<s.size()<<endl;
{
s.extract(siz[x]);
s.extract(siz[abs(y)]);
if(y>0)siz[y][0]+=siz[x][0],siz[y][1]+=siz[x][1];
else siz[-y][0]+=siz[x][1],siz[-y][1]+=siz[x][0];
s.insert(siz[abs(y)]);
if(check()){
f[x]=y;return true;
}
s.extract(siz[abs(y)]);
if(y>0)siz[y][0]-=siz[x][0],siz[y][1]-=siz[x][1];
else siz[-y][0]-=siz[x][1],siz[-y][1]-=siz[x][0];
s.insert(siz[x]);
s.insert(siz[abs(y)]);
return false;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n*2;i++)f[i]=i,siz[i][0]=1,s.insert(siz[i]);
vector<int> ans(n*2+1,0);
vector<pair<int,int>> q(m);
for(int i=0;i<m;i++){
cin>>q[i].first>>q[i].second;
}
reverse(q.begin(),q.end());
string anss;
for(auto [x,y]:q){
bool flag=merge(x,-y);
if(!flag)merge(x,y);
if(flag)anss.push_back('1');
else anss.push_back('0');
// cout<<"x="<<x<<" y="<<y<<" merge="<<flag<<endl;
}
// for(int i=1;i<=n;i++)cout<<
vector<int> vis(n*2+1,0);
vector<pair<vector<int>,vector<int>>>all;
vector<vector<int>> dp(n*2+1,vector<int>(n+1));
dp[0][0]=1;
int p=0;
for(int i=1;i<=n*2;i++)if(!vis[i]){
vector<int> v0,v1;
v0.push_back(i);
p++;
for(int j=i+1;j<=n*2;j++)if(abs(getf(i))==abs(getf(j))){
if(getf(i)==-getf(j))v1.push_back(j);
else v0.push_back(j);
vis[j]=1;
}
all.emplace_back(v0,v1);
for(int j=0;j<=n;j++){
if(j>=v0.size())dp[p][j]|=dp[p-1][j-v0.size()];
if(j>=v1.size())dp[p][j]|=dp[p-1][j-v1.size()];
}
// cout<<"v0 :";for(auto it:v0)cout<<it<<" ";;cout<<endl;
// cout<<"v1 :";for(auto it:v1)cout<<it<<" ";;cout<<endl;
}
reverse(all.begin(),all.end());
int now=n;
// cout<<"???"<<endl;
for(auto [v0,v1]:all){
// cout<<"p="<<p<<" now="<<now<<endl;
if(now>=v0.size()&&dp[p-1][now-v0.size()]){
for(auto it:v0)ans[it]=0;
for(auto it:v1)ans[it]=1;
now-=v0.size();
}
else if(now>=v1.size()&&dp[p-1][now-v1.size()]){
for(auto it:v0)ans[it]=1;
for(auto it:v1)ans[it]=0;
now-=v1.size();
}
p--;
}
assert(p==0&&now==0);
int cnt[2]={0,0};
for(int i=1;i<=2*n;i++)cnt[ans[i]]++;
assert(cnt[0]==cnt[1]);
for(int i=1;i<=2*n;i++)cout<<ans[i];;cout<<endl;
// cout<<anss;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 3ms
memory: 11332kb
input:
2 4 1 3 2 4 1 4 1 2
output:
0101
result:
ok Output is valid. OK
Test #2:
score: 0
Accepted
time: 6ms
memory: 11156kb
input:
3 7 2 5 1 3 4 6 2 6 4 5 2 4 5 6
output:
001101
result:
ok Output is valid. OK
Test #3:
score: 0
Accepted
time: 3ms
memory: 11284kb
input:
1 0
output:
10
result:
ok Output is valid. OK
Test #4:
score: 0
Accepted
time: 6ms
memory: 11108kb
input:
1 1 1 2
output:
01
result:
ok Output is valid. OK
Test #5:
score: 0
Accepted
time: 3ms
memory: 11144kb
input:
2 3 2 4 3 4 1 2
output:
0110
result:
ok Output is valid. OK
Test #6:
score: 0
Accepted
time: 3ms
memory: 11148kb
input:
3 8 4 6 3 5 1 4 2 4 1 6 1 2 3 4 4 5
output:
010101
result:
ok Output is valid. OK
Test #7:
score: 0
Accepted
time: 3ms
memory: 11108kb
input:
4 9 4 7 3 8 1 5 2 7 2 8 6 8 7 8 1 4 1 6
output:
01010110
result:
ok Output is valid. OK
Test #8:
score: 0
Accepted
time: 7ms
memory: 11284kb
input:
5 16 3 6 9 10 2 7 1 10 1 5 2 10 3 5 5 6 3 4 2 5 4 5 3 8 4 7 6 8 1 6 7 10
output:
0010111010
result:
ok Output is valid. OK
Test #9:
score: 0
Accepted
time: 3ms
memory: 11320kb
input:
6 13 4 5 2 9 3 8 4 8 4 11 10 12 3 4 3 9 5 11 2 8 5 10 5 8 1 11
output:
110110001001
result:
ok Output is valid. OK
Test #10:
score: 0
Accepted
time: 3ms
memory: 11420kb
input:
12 153 1 24 16 18 7 14 1 16 20 21 9 14 21 22 4 5 17 24 4 12 5 17 13 24 14 15 12 23 12 16 8 11 14 24 9 16 2 5 6 19 11 17 4 22 4 7 6 16 7 20 8 15 5 24 2 10 10 21 21 24 1 12 11 19 18 21 18 24 12 17 13 22 7 9 13 23 4 9 11 13 15 21 5 7 2 4 15 16 17 19 11 16 11 20 7 8 4 15 13 14 6 18 2 19 9 13 23 24 4 21 ...
output:
000011100110010001111110
result:
ok Output is valid. OK
Test #11:
score: 0
Accepted
time: 63ms
memory: 12508kb
input:
259 33757 472 500 65 336 138 469 307 442 427 458 43 239 17 508 460 466 108 393 79 92 250 483 44 277 17 132 35 57 155 499 184 474 246 272 274 418 457 458 338 372 196 514 31 208 117 187 90 229 153 284 189 355 16 337 146 456 269 271 279 412 305 336 303 441 399 472 85 286 91 97 157 437 137 379 71 360 27...
output:
000111001101000110010001111000111111100000011101010011011101110001010010000001111000111010000011101001010001000011100101010011000101101100010101100101100101100010011000110100001110011000111101010100011001001110110101101101010101101001100110011110101001111011110001010001111101001110101101111001001100...
result:
ok Output is valid. OK
Test #12:
score: 0
Accepted
time: 786ms
memory: 19264kb
input:
811 265557 217 1153 383 1609 165 177 612 1602 1057 1428 37 436 135 1200 368 684 448 722 145 1583 325 1052 246 480 74 148 122 1111 1256 1327 304 1070 1285 1542 802 813 454 1563 265 1193 94 848 432 1156 429 1194 427 1230 1152 1406 1329 1355 702 845 591 1232 877 1288 1257 1549 340 659 1080 1333 910 137...
output:
001000000010111000100000000010100001011010111010110111111110000111010000101011011010001011001010111000001011000011011001000001011010001010000011100001010101100110010101011001101100100000100100001010000000100111110011110010001000000001011101100011100001000000101110100000001001100000011110101100100010...
result:
ok Output is valid. OK
Test #13:
score: -100
Time Limit Exceeded
input:
1691 323743 1246 2397 1445 2647 2010 2806 2001 2896 802 2258 2679 2976 2203 2875 2445 2698 137 3004 536 1800 2316 2520 594 1517 279 1558 1934 2871 57 1358 357 976 1764 2672 869 2137 1694 2201 491 1906 1177 1414 1304 1377 2454 2653 626 2637 1425 1677 620 876 1326 2085 404 874 626 1565 136 597 2885 31...