以 P10304 为例,记录一下 MatrixGroup 的当前码风
MatrixGroup · · 个人记录
#include <bits/stdc++.h>
#define rep(i,n) for(int i=0,del##i##verme=int(n);i<del##i##verme;++i)
#define rep1(i,n) for(int i=1,parano##i##a=int(n);i<=parano##i##a;++i)
#define per(i,n) for(int i=int(n)-1;i>=0;--i)
#define per1(i,n) for(int i=int(n);i>=1;--i)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define y0 LingLuo
#define y1 VividCycle
typedef long long ll;
typedef unsigned long long ull;
typedef long double ldb;
using namespace std;
const ll mod1=998244353;
const ll mod2=1000000007;
unsigned time_related_rand()
{
return unsigned(std::chrono::steady_clock::now().time_since_epoch().count());
}
int n,m,q,u,v;
struct dsu{
int p[100005];
void init(int N)
{
rep1(i,N) p[i]=i;
}
int getp(int x)
{
return (p[x]==x)?x:(p[x]=getp(p[x]));
}
void merge(int x,int y)
{
p[getp(x)]=getp(y);
}
};
struct fenwick{
int s[100005];
void add(int x,int val)
{
while(x<=n)
{
s[x]+=val;
x+=x&-x;
}
}
int query(int x)
{
int r=0;
while(x)
{
r+=s[x];
x&=x-1;
}
return r;
}
};
dsu D;
fenwick tree;
vector<int> to[100005],tre[100005],fr[100005];int deg[100005];
int dep[100005],par[18][100005];
int c[100005];
int f[100005][18];
bool vis[100005];
int bg[100005],ed[100005],toki;
vector<pair<int,int> > query[100005];
queue<int> Q;
vector<int> id[100005];
int answer[100005];
void dfs(int ver)
{
vis[ver]=true;bg[ver]=++toki;
for(int x:to[ver])
{
++deg[x];
if(!vis[x])
{
dep[x]=dep[ver]+1;dfs(x);tre[ver].pb(x);par[0][x]=ver;
}
else
{
fr[x].pb(ver);
}
}
ed[ver]=toki;
}
int value(int x,int y)
{
int vv=0x3f3f3f3f;
if(dep[x]>=dep[y])
{
int d=dep[x]-dep[y];
rep(i,18) if((d>>i)&1) x=par[i][x];
}
else
{
int d=dep[y]-dep[x];
rep(i,18) if((d>>i)&1) {vv=min(vv,f[y][i]);y=par[i][y];}
}
if(x==y) return min(vv,c[y]);
per(i,18) if(par[i][x]!=par[i][y])
{
x=par[i][x];vv=min(vv,f[y][i]);y=par[i][y];
}
return min(vv,f[y][1]);
}
void link(int x,int y)
{
int val=tree.query(ed[y])-tree.query(bg[y]-1);
D.merge(y,x);
tree.add(bg[x],val);
if(D.getp(x)!=1)
tree.add(bg[par[0][D.getp(x)]],-val);
}
int main()
{
ios_base::sync_with_stdio(false);cin.tie(0);
cin>>n>>m>>q;
rep1(i,m)
{
cin>>u>>v;to[u].pb(v);
}
rep1(i,n) sort(to[i].begin(),to[i].end());
dfs(1);
rep1(i,17)
{
rep1(j,n) par[i][j]=par[i-1][par[i-1][j]];
}
rep1(i,n) if(deg[i]==0) Q.push(i);
rep(i,18) f[0][i]=0x3f3f3f3f;
while(!Q.empty())
{
int x=Q.front();Q.pop();
c[x]=dep[x];
for(int y:fr[x])
{
c[x]=min(c[x],value(x,y));
}
for(int y:to[x])
{
if((--deg[y])==0) Q.push(y);
}
f[x][0]=c[x];
rep1(i,17)
{
f[x][i]=min(f[x][i-1],f[par[i-1][x]][i-1]);
}
id[c[x]].pb(x);
}
rep1(i,q)
{
cin>>u>>v;query[dep[u]].pb(mp(v,i));
}
rep1(i,n) vis[i]=false;
D.init(n);
per(i,n)
{
for(pair<int,int> P:query[i])
{
answer[P.se]=tree.query(ed[P.fi])-tree.query(bg[P.fi]-1);
}
for(int ver:id[i])
{
tree.add(bg[ver],1);
if(ver!=1) tree.add(bg[par[0][ver]],-1);
vis[ver]=true;
for(int chd:tre[ver])
{
if(vis[chd]) link(ver,chd);
}
if(vis[par[0][ver]]) link(par[0][ver],ver);
}
}
rep1(i,q) cout<<answer[i]<<'\n';
return 0;
}
/* things to check
1. int overflow or long long memory need
2. recursion/array/binary search/dp/loop bounds
3. precision
4. special cases(n=1,bounds)
5. delete debug statements
6. initialize(especially multi-tests)
7. = or == , n or m ,++ or -- , i or j , > or >= , < or <=
8. keep it simple and stupid
9. do not delete, use // instead
10. operator priority
11. is there anything extra to output?
12. ...
*/
/* something to think about
1. greedy? dp? searching? dp with matrix/ segment tree? binary search?
2. If contains "not", why not ?????? or few affect?
*/
这里给出一点解释:
dsu D;和fenwick tree;:数据结构定式。类似的还有segtree seg;和Trie T;等。[100005]:除非有块长,数组大小手打。最后一个加的数为\max(5,\left\lfloor\log_{10}n\right\rfloor) ,例如[1005],[10000007]。- 写了
things to check但是从来不会去看。 - 对于
for循环,一般使用rep系列,如果范围非正常范围或闲得无聊单独写。(例如读入树的p 数组使用for(int i=2;i<=n;++i))以上二者变量名为i,j,k,l,m系列,如果变量名重复则跳过。对于 rangefor循环,整数变量名使用x,y,z,w系列或有明确意义的ver,nei,query,有序对变量名使用P等。 vv:本为v,但是看不惯变量重名爆 warning,遂修改为第一个相当的类似变量名并替换。toki:时间戳,一开始想的为t,但是可能造成混淆,time容易与标准库重名,选用t开头的toki(時、とき)。vector<int> to[100005],tre[100005],fr[100005];int deg[100005];:一开始把deg和前面三个定义在一起了,然后改的时候懒得换行。par[18][100005]:倍增数组,18开在前面利于连续访问。f[100005][18]:动态维护的倍增数组。18开在后面利于连续访问。vector<pair<int,int> >:不喜欢两个>写一起。