因为 他只对 我的子数组求和的时候取模,整体并没有取模,所以不能计算每个元素的贡献。
我们在求 前缀和的时候,直接对前缀和取模。
对应子数组的和的问题转化成 前缀和的差。
当我的 sr>sl-1 的时候 不变
else 我么要加上一个M
我们将这这些分开来算,每个前缀和的贡献加上 额外M
这个M的数量就是 sr<sl-1 的数量。也就是 s 数组的逆序对的数量。
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read()
{
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
return x * f;
}
const int N=2e5+10;
int n, p;
int ranks[N];
int s[N];
struct node
{
int value,pos;
}a[N];
bool cmp(node &a,node &b)
{
if (a.value==b.value)
return a.pos<b.pos;
return a.value<b.value;
}
int lowbit(int x)
{
return x&-x;
}
void change(int x,int k)
{
while(x<=n)
{
s[x]+=k;x+=lowbit(x);
}
}
int query(int x)
{
int t=0;
while(x)
{
t+=s[x];
x-=lowbit(x);
}
return t;
}
void solve()
{
cin >> n >> p;
vector<int> ss(n + 1);
for (int i = 1, t; i <= n; i++)
{
cin >> t;
ss[i] = (ss[i - 1] + t)%p;
a[i].value=ss[i]%p;
a[i].pos=i;
}
sort(a+1,a+n+1,cmp);
for (int i=1;i<=n;i++)
{
ranks[a[i].pos]=i;
}
int res=0;
for (int i=1;i<=n;i++)
{
change(ranks[i],1);
res+=i-query(ranks[i]);
}
int ans=res*p;
// 作为后缀
for (int i=1;i<=n;i++)
{
ans+=ss[i]*(i);
}
// 作为前缀
for (int i=1;i<=n;i++)
{
ans-=ss[i]*(n-(i+1)+1);
}
cout<<ans<<"\n";
}
signed main()
{
std::cin.tie(nullptr)->sync_with_stdio(false);
int t = 1;
// cin>>t;
while (t--)
{
solve();
}
return 0;
}
F
加上一条边 使得 形成一个 所用点的度都是 3 的环。
加上一条边,会使得两个点的度都增加1.所以 在没加边之前。是两个度为2的点。这个环里的其他点 的度 本来就是3.
也就是说 我们要找到 有多少 对 度数 为 2 的点,他们路径上的点 的度数都是3 。
这么想 十分难以实现。我们不防换个角度。不要盯着度数为2的点。
我们可以 处理出来度数为3 的联通块。我们符合条件的 度数为2 的点,就是这些连通块 向外走一步出来的点(度数为2)
从度数为3的点进入dfs,在dfs 中 遇到的度数为2的点,就是符合条件的点。
也可以这么想 我们 不会递归 度数不为三的点,那么在dfs 中碰到的其他点,都是 我这个连通块 和外界相连的第一个点
#include <bits/stdc++.h>
using namespace std;
#define int long long
int read()
{
int x = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch))
{
x = (x << 1) + (x << 3) + ch - '0';
ch = getchar();
}
return x * f;
}
const int N = 2e5 + 5;
vector<int> e[N];
void solve()
{
int n;
cin >> n;
vector<int> du(n + 1);
for (int i = 0, u, v; i < n - 1; i++)
{
cin >> u >> v;
e[u].push_back(v);
e[v].push_back(u);
du[u]++;
du[v]++;
}
vector<int>vis(n+1);
int t=0;
auto dfs=[&](auto &&self,int u,int fa)->void
{
for (auto v:e[u])
{
if (v==fa)continue;
if (vis[v])continue;
t+=(du[v]==2);
if(du[v]==3)
{
vis[v]=1;
self(self,v,u);
}
}
};
int ans=0;
for (int i=1;i<=n;i++)
{
if (du[i]==3)
{
if (vis[i])continue;
t=0;
dfs(dfs,i,-1);
ans+=(t)*(t-1)/2;
}
}
cout<<ans<<"\n";
}
signed main()
{
std::cin.tie(nullptr)->sync_with_stdio(false);
int t = 1;
// cin>>t;
while (t--)
{
solve();
}
return 0;
}