# Factorial of T1 puzzle

## Problem solving ideas

After two answers, it is found that \ (a-b \) is at most 19. After all \ (20! \) is greater than \ (10 ^ {18} \).

For each possible difference, each bisection \ (b+1 \) directly enumerates the product for check.

## code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
int T,n,fac[20];
inline int work(int x,int cnt)
{
__int128 temp=1;
for(int i=1;i<=cnt;i++)
{
temp*=x+i-1;
if(temp>n) return 1;
}
if(temp==n) return 0;return -1;
}
void solve()
{
vector<pair<int,int> > ans;
for(int cnt=1;cnt<=19&&fac[cnt]<=n;cnt++)
{
int l=2,r=n-cnt+1,temp=-1;
while(l<=r)
{
int mid=(l+r)>>1,t=work(mid,cnt);
if(!t){temp=mid;break;}
if(t==-1) l=mid+1; else r=mid-1;
}
if(~temp) ans.push_back(make_pair(temp+cnt-1,temp-1));
}
sort(ans.begin(),ans.end()); printf("%lld\n",(int)ans.size());
for(auto it :ans) printf("%lld %lld\n",it.first,it.second);
}
#undef int
int main()
{
#define int long long
freopen("factorial.in","r",stdin); freopen("factorial.out","w",stdout);
for(int i=1;i<=19;i++) fac[i]=fac[i-1]*i;
while(T--) solve();
return 0;
}


# T2 subset

## Problem solving ideas

Assuming that the size of each set is \ (cnt \), if \ (cnt \) is even, you can directly fill in different orders for parity.

Then it can be proved that it is not feasible when \ (n \) is even but \ (cnt \) is odd.

Then, when \ (k,cnt \) are all odd numbers, it is found that if the first three of each set can be successfully arranged, the rest will be treated as even numbers.

For the first column, it's good to arrange directly \ (1,2,3...n \), and for the second column, it's good to fill in the section of \ (\ frac{k+1}{2}+1\sim k \) from large to small, and then fill in the section of \ (1\sim\frac{k+1}{2} \) from large to small.

For the remaining column, it is good to supplement it directly according to the situation of the first two columns.

## code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
#define count __builtin_popcountll
using namespace std;
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e6+10;
int T,n,m,cnt;
vector<int> ans[N];
void work1(int bas,int all)
{
for(int i=1;i<=all;i++)
if(i&1) for(int j=1;j<=m;j++) ans[j].push_back(++bas);
else for(int j=m;j>=1;j--) ans[j].push_back(++bas);
}
void work2(int bas=0)
{
for(int i=1;i<=m;i++) ans[i].push_back(++bas);
for(int i=m/2+2;i<=m;i++) ans[i].push_back(++bas);
for(int i=1;i<=m/2+1;i++) ans[i].push_back(++bas);
for(int i=1;i<=m;i++) ans[i].push_back(3*(3*m+1)/2-ans[i][0]-ans[i][1]);
}
void solve()
{
if(m==1){printf("Yes\n");for(int i=1;i<=n;i++)printf("%lld ",i);putchar('\n');return ;}
if(n%2==0&&cnt%2) return printf("No\n"),void();
if(cnt%2&&cnt<3) return printf("No\n"),void();
for(int i=1;i<=m;i++) vector<int>().swap(ans[i]); printf("Yes\n");
if(cnt%2==0) work1(0,cnt);
else work2(),work1(3*m,cnt-3);
for(int i=1;i<=m;i++)
{
for(auto it:ans[i]) printf("%lld ",it);
putchar('\n');
}
}
#undef int
int main()
{
#define int long long
freopen("subset.in","r",stdin); freopen("subset.out","w",stdout);
return 0;
}


# T3 concrete powder

## Problem solving ideas

The essence of query is to add intervals several times and ask the time when the value at the position of \ (x \) is the earliest \ (\ ge y \).

So we can select the chairman tree, and then the violent dichotomy + chairman tree can reach the complexity of \ (O(qlog^2n) \), and then it will be stuck.

Consider an offline approach. For each insertion operation \ ((l,r,h) \), we record a binary \ ((id,h) \) in two places \ (l,r+1 \).

Then scan the sequence of line scan \ (1\sim n \) and process the answer with a tree array or line segment tree based on the operation label to maintain the height.

In this way, we have the relative time relationship and corresponding height of all influential operations for each subscript.

Find one answer in two at a time. The subscript \ (mid \) uses the tree array to find the height reached by the \ (mid \) operation and previous operations. check.

This is the binary tree array. Because the constant is excellent, it can be stuck. The binary of line segment tree or tree array is also a similar idea.

## code

### Super constant chairman tree

#include<bits/stdc++.h>
#define ll long long
#define ls tre[x].l
#define rs tre[x].r
using namespace std;
{
ll x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e6+10;
int n,q,all,rt,root[N],id[N]; ll cnt;
struct Segment_Tree
{
struct Node{int l,r;ll dat;}tre[N*35];
inline int insert(register int pre,register int l,register int r,register int L,register int R,register int val)
{
register int x=++all,mid=(l+r)>>1; tre[x]=tre[pre];
if(L<=l&&r<=R) return tre[x].dat+=val,x;
if(L<=mid) ls=insert(tre[pre].l,l,mid,L,R,val);
if(R>mid) rs=insert(tre[pre].r,mid+1,r,L,R,val);
return x;
}
inline void query(register int x,register int l,register int r,register int pos)
{
if(!x||l==r) return cnt+=tre[x].dat,void(); register int mid=(l+r)>>1;
if(pos<=mid) return cnt+=tre[x].dat,query(ls,l,mid,pos),void();
return cnt+=tre[x].dat,query(rs,mid+1,r,pos),void();
}
}T;
int main()
{
freopen("concrete.in","r",stdin); freopen("concrete.out","w",stdout);
for(register int i=1,opt,x,z;i<=q;i++)
{
T.query(root[rt],1,n,x); if(cnt<y){printf("0\n");continue;}
register int l=0,r=rt,ans=0;
while(l<=r)
{
register int mid=(l+r)>>1; cnt=0; T.query(root[mid],1,n,x);
if(cnt>=y) ans=id[mid],r=mid-1; else l=mid+1;
}
printf("%d\n",ans);
}
return 0;
}



### Binary tree array

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e6+10;
int n,q,cnt,ans[N];
struct BIT
{
int lim,tre[N];
#define lowbit(x) (x&(-x))
inline void insert(int x,int val){for(int i=x;i<=lim;i+=lowbit(i))tre[i]+=val;}
inline int query(int x){int sum=0;for(int i=x;i;i-=lowbit(i))sum+=tre[i];return sum;}
}T;
#undef int
int main()
{
#define int long long
freopen("concrete.in","r",stdin); freopen("concrete.out","w",stdout);
for(int i=1,opt,x,y,z;i<=q;i++)
{
v[y+1].push_back(make_pair(i,-z));
}
for(int i=1;i<=n;i++)
{
for(auto it:v[i]) T.insert(it.first,it.second);
{
int l=1,r=it.first; ans[it.first]=0;
while(l<=r)
{
int mid=(l+r)>>1,temp=T.query(mid);
if(temp>=it.second) ans[it.first]=mid,r=mid-1;
else l=mid+1;
}
}
}
for(int i=1;i<=q;i++) if(~ans[i]) printf("%lld\n",ans[i]);
return 0;
}


# T4 drainage system

## Problem solving ideas

Consider the effect of edge \ ((x,y) \) blockage.

In fact, the contribution to other outlets of \ (x \) increases, while the contribution to \ (y \) decreases.

It means that we can add the contribution to the \ (x \) point and then subtract it from the \ (y \) point.

The specific realization is to ignore all aging conditions, calculate that there should be sewage at each point, and then calculate the initial expected sewage at each point on the basis of sequence.

Just run again at last.

## code

#include<bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"RP++"<<endl
using namespace std;
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=2e5+10,M=5e5+10,mod=998244353;
int n,m,base,sta[N],r,ed,cnt[N],du[N],f[N],g[N];
{
ver[++tot]=y; edge[tot]=val;
fro[tot]=x; du[y]++; cnt[x]++;
}
int power(int x,int y,int p=mod)
{
int temp=1;
for(;y;y>>=1,x=x*x%p)
if(y&1) temp=temp*x%p;
return temp;
}
#undef int
int main()
{
#define int long long
freopen("water.in","r",stdin); freopen("water.out","w",stdout);
for(int i=1,x,y,val;i<=ed;i++)
{
}
int top=0,pos=0; base=power(base,mod-2);
for(int i=1;i<=m;i++) sta[++top]=i;
while(top<n)
{
int x=sta[++pos];
{
int to=ver[i]; du[to]--;
if(!du[to]) sta[++top]=to;
}
}
for(int i=1;i<=m;i++) f[i]=1;
for(int i=1;i<=n;i++)
{
int x=sta[i],temp=power(cnt[x],mod-2)*f[x]%mod;
}
for(int i=1;i<=n;i++)
{
if(!cnt[i]) continue;
int temp=f[i]*power(cnt[i]-1,mod-2)%mod;
{
}
}