csp-s模拟3
A. 奇观
观察到 \(c\) 和 \(f\) 互不影响,所以分开算就行,枚举相连的边太多了,会 \(T\),所以我们把总情况找出来,减去删去的边的
方案数即可,记 \(f_{u,x}\) 表示 \(u\) 节点往后跟 \(x\) 个长度的方案数,有 \(f_{u,x}=\sum_{x->y} \limits f_{y,x-1}\)
边界 \(f_{u,1}=\) 其度数,这是 \(c\) 的,\(f\) 就是长度为 \(3\) 的链后面随便取俩点
点击查看代码
#include<bits/stdc++.h>
#define int long long
const int mod=998244353;
const int maxn=1e5+10;
using namespace std;
int n,m,sum,ans,temp,in[maxn];
int f[maxn][4];
vector<int>q[maxn];
unordered_map<int,int>a[maxn];
signed main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
fill(in+1,in+1+n,n-1);
for(int i=1,x,y;i<=m;i++)
{
cin>>x>>y;
in[x]--,in[y]--;
q[x].push_back(y);
q[y].push_back(x);
}
for(int i=1;i<=n;i++)
{
f[i][1]=in[i];
temp=(temp+f[i][1])%mod;
}
for(int i=1;i<=n;i++)
{
f[i][2]=temp-f[i][1];
for(int j=0;j<q[i].size();j++)
{
f[i][2]-=f[q[i][j]][1];
}
ans=(ans+f[i][2])%mod;
}
temp=0;
for(int i=1;i<=n;i++)
{
f[i][3]=ans-f[i][2];
for(int j=0;j<q[i].size();j++)
{
f[i][3]-=f[q[i][j]][2];
}
temp=(temp+f[i][3])%mod;
}
// cout<<temp;
sum=1ll*temp*temp%mod;
ans=0;
for(int i=1;i<=n;i++)
{
ans=(ans+1ll*f[i][2]*in[i]%mod*in[i]%mod)%mod;
}
// cout<<ans;
cout<<1ll*sum*ans%mod;
return 0;
}
/*
4 1
1 2
*/
B. 铁路
新开一个数组来对应新建节点的位置,把位置指到合并的点中深度最小的点即可,这里合并时用并查集维护每个联通块
压缩路径也到深度最小的点,这样就对应起来了
点击查看代码
#include<bits/stdc++.h>
const int maxn=5e5+10;
using namespace std;
int head[maxn],nxt[maxn<<1],to[maxn<<1],tot;
int n,m,fa[maxn],last[maxn],pos[maxn<<1],size;
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
void addm(int x,int y)
{
add(x,y),add(y,x);
}
int pre[maxn],deep[maxn],st[20][maxn],cnt;
struct Lca
{
int get(int x,int y){return deep[x]<deep[y]?x:y;}
void lsx(int x,int fa)
{
pre[x]=++cnt,last[x]=fa,st[0][cnt]=fa;deep[x]=deep[fa]+1;
for(int i=head[x];i;i=nxt[i]) if(to[i]!=fa) lsx(to[i],x);
}
void init()
{
lsx(1,0);
for(int i=1;(1<<i)<=n;i++)
for(int j=1;j<=n-(1<<i)+1;j++)
st[i][j]=get(st[i-1][j],st[i-1][j+(1<<i-1)]);
}
int lca(int x,int y)
{
if(x==y) return x;
if((x=pre[x])>(y=pre[y])) swap(x,y);
int l=__lg(y-x);
return get(st[l][x+1],st[l][y-(1<<l)+1]);
}
}e;
void merge(int x,int y,int i)
{
int p=e.lca(x,y);
int a=find(x),b=find(y),c=find(p);
// cout<<a<<" "<<b<<" "<<p<<endl;
while(find(a)!=find(c))
{
a=fa[a]=find(last[a]);
size--;
}
while(find(b)!=find(c))
{
// cout<<b<<" "<<last[b]<<"!"<<endl;
b=fa[b]=find(last[b]);
size--;
}
pos[n+i]=c;
}
int main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n>>m;
size=n;
for(int i=1;i<=n;i++)fa[i]=i,pos[i]=i;
for(int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
addm(x,y);
}
e.init();
for(int i=1;i<=m;i++)
{
int x,y;
cin>>x>>y;
x=pos[x];
y=pos[y];
// cout<<x<<" "<<y<<"!"<<endl;
merge(x,y,i);
cout<<size<<'\n';
}
return 0;
}
/*
10 5
2 1
9 7
4 10
1 8
3 4
1 7
3 2
6 1
1 5
1 6
8 4
5 12
13 13
9 14
*/
C. 光纤
破防了,这东西谁愿意改谁改,我改不了一点。。。
改出来了!!!
找凸包的每一条边的高,找最小的那个就是答案
点击查看代码
#include<bits/stdc++.h>
#define int __int128
const int maxn=1e6+10;
using namespace std;
typedef pair<int,int>pr;
int n,top,st[maxn];
pr p[maxn];
bool used[maxn];
template<typename T> inline T read() {
T X = 0; bool flag = 1; char ch = getchar();
while (ch < '0' || ch > '9') {if (ch == '-') flag = 0; ch = getchar();}
while (ch >= '0' && ch <= '9') {X = (X << 1) + (X << 3) + ch - '0'; ch = getchar();}
if (flag) return X;
return ~ (X - 1);
}
template<typename T> inline void write(T X) {
if (X < 0) {putchar('-'); X = ~ (X - 1);}
int s[50], top = 0;
while (X) {s[++top] = X % 10; X /= 10;}
if (!top) s[++top] = 0;
while (top) putchar(s[top--] + '0');
return;
}
pr operator - (pr a,pr b)
{
return {a.first-b.first,a.second-b.second};
}
int cross(pr a,pr b,pr c)
{
pr u,v;
u=b-a,v=c-a;
// if(u.first*v.second-v.first*u.second<0)exit(11);
return u.first*v.second-v.first*u.second;
}
pr s1(pr a,pr b,pr c)
{
pr u,v;
u=b-a,v=c-a;
int x=(u.first*v.second-v.first*u.second);
// write(x);
// cout<<endl;
return {x*x,u.first*u.first+u.second*u.second};
}
void pre()
{
sort(p+1,p+n+1);
int num=unique(p+1,p+1+n)-p-1;
n=num;
// cout<<n<<endl;
// write(n);
// cout<<endl;
for(int i=1;i<=n;i++)
{
while(top>=2&&cross(p[st[top-1]],p[st[top]],p[i])>0)
{
used[st[top]]=0;
top--;
}
st[++top]=i;
used[i]=1;
}
used[1]=0;
for(int i=n-1;i>=1;i--)
{
if(used[i])continue;
while(top>=2&&cross(p[st[top-1]],p[st[top]],p[i])>0) top--;
st[++top]=i;
}
// cout<<top<<endl;
// write(top);
}
pr yue(pr x)
{
int a=x.first,b=x.second;
int c=__gcd(a,b);
return {a/c,b/c};
}
bool cmp(pr a,pr b)
{
if(!b.first) return 1;
pr c=yue(a),d=yue(b);
if(c.second!=d.second)
{
long double cc,dd;
cc=1.0*a.first/a.second,dd=1.0*b.first/b.second;
// c={a.first*b.second,a.second*b.second};
// d={b.first*a.second,b.second*a.second};
// if(cc<0)
// {
//cout<<cc;
// cout<<endl;
// }
// cout<<(signed)cc<<" "<<(signed)dd<<endl;
return 1.0*cc>=1.0*dd?1:0;
}
// cout<<endl;
return c.first>=d.first?1:0;
}
pr min(pr a,pr b)
{
if(!b.first) return a;
return cmp(a,b)?b:a;
}
void solve()
{
pr a=p[st[1]],b=p[st[2]],c=p[st[3]];
pr ans=s1(a,b,c);
int k=3;
// write(ans.first),cout<<" ",write(ans.second),cout<<endl;
for(int i=4;i<top;i++)
{
pr d=s1(a,b,p[st[i]]);
if(cmp(d,ans))
{
// write(d.second);
// cout<<' ';
// write(ans.second);
// cout<<' ';
// write(i);
// cout<<endl<<endl;
ans=d;
k=i;
}
}
// pr kk=yue({ans.first,ans.second*4});
// write(k);
// cout<<endl;
// write(st[k]);
// cout<<endl<<endl;
// write(kk.first);
// cout<<endl;
int x=2,y=3;
// cout<<"----------------------";
// write(top-1);
// cout<<endl;
for(int i=k,cnt=1;cnt<=top-1;cnt++,x=x%(top-1)+1,y=y%(top-1)+1)
{
// write(i);
// cout<<endl;
pr l={0,1};
while(1)
{
a=p[st[x]],b=p[st[y]],c=p[st[i]];
pr d=s1(a,b,c);
d=yue(d);
// write(d.first);
// cout<<" ";
// write(l.first);
// cout<<endl;
if(cmp(d,l)) l=d;
else
{
i--;
if(!i) i=top-1;
break;
}
i=i%(top-1)+1;
//if(i%(top-1)+1==x||i%(top-1)+1==y) break;
}
// write(x);cout<<" ";write(y);cout<<" ";write(i);cout<<endl;
// write(l.first);
// ans=min(ans,l);
// write(ans.first),cout<<"!! ",write(ans.second),cout<<endl;
// write(l.first),cout<<"$$ ",write(l.second),cout<<endl;
if(cmp(ans,l)&&l.first!=0)
{
ans=l;
// write(ans.first),cout<<"%% ",write(ans.second),cout<<endl;
//cout<<x<<" "<<i<<" "<<y<<endl;
// write(st[x]);
// cout<<' ';
// write(st[y]);
// cout<<" ";
// write(st[i]);
// cout<<endl;
}
}
// cout<<ans.first<<" "<<ans.second<<endl;
// wrr()
// if(ans.second*4<0)exit(11);
ans={ans.first,ans.second*4};
ans=yue(ans);
write(ans.first);
cout<<"/";
write(ans.second);
}
signed main()
{
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
// ios::sync_with_stdio(0);
// cin.tie(0),cout.tie(0);
n=read<int>();
if(n==2)
{
cout<<"0/1";
return 0;
}
for(int i=1;i<=n;i++)
{
int x,y;
x=read<int>(),y=read<int>();
p[i]={x,y};
}
pre();
// for(int i=0;i<=top+1;i++)
// {
// write(p[st[i]].first);
// cout<<' ';
// write(p[st[i]].second);
// cout<<endl;
// }
// pr kk=s1(p[st[1]],p[st[2]],p[st[6]]);
// kk.second*=4;
// kk=yue(kk);
// write(kk.first);
// cout<<" ";
// write(kk.second);
// write(top-1);
// cout<<endl;
solve();
return 0;
}
/*
4
4964 8815
11110 29358
10495 2433
9678 32476
*/