题解 简单的区间
因为把(tl(p)+tr(p))>>1
打成(tl(p)+tl(p))>>1
氪了快两个小时都没调对
解法和这题类似,把可持久化01trie换成主席树即可
但是字母一定要打对……
Code:
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000100
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
ll k, a[N], ans, sum[N];
struct que{ll val; int pos; inline void build(ll v_, int p_) {val=v_; pos=p_;}}q[N];
namespace force{
void solve() {
for (int len=2,l,r; len<=n; ++len) {
l=1; r=0;
for (int i=1; i<len; ++i) {
while (l<=r && a[i]>=q[r].val) --r;
q[++r].build(a[i], i);
}
for (int i=len; i<=n; ++i) {
while (l<=r && q[l].pos<=i-len) ++l;
while (l<=r && q[r].val<=a[i]) --r;
q[++r].build(a[i], i);
if ((sum[i]-sum[i-len]-q[l].val)%k==0) ++ans;
}
}
printf("%lld\n", ans);
}
}
namespace task1{
int l[N], r[N], ql, qr;
const int SIZE=N*10;
int tot, rot[N], tl[SIZE], tr[SIZE], cnt[SIZE], lson[SIZE], rson[SIZE];
#define tl(p) tl[p]
#define tr(p) tr[p]
#define cnt(p) cnt[p]
#define l(p) lson[p]
#define r(p) rson[p]
#define pushup(p) cnt(p)=cnt(l(p))+cnt(r(p))
void upd(int p1, int& p2, int l, int r, int pos) {
//cout<<"upd: "<<l<<' '<<r<<' '<<pos<<endl;
if (!p2) {p2=++tot; tl(p2)=l; tr(p2)=r;}
if (l>=r) {cnt(p2)=cnt(p1)+1; return ;}
int mid=(l+r)>>1;
if (pos<=mid) {
r(p2)=r(p1);
upd(l(p1), l(p2), l, mid, pos);
}
else {
l(p2)=l(p1);
upd(r(p1), r(p2), mid+1, r, pos);
}
pushup(p2);
}
int query(int p1, int p2, int pos) {
//cout<<"query "<<tl(p2)<<' '<<tr(p2)<<' '<<pos<<endl;
if (!p2 || !(cnt(p2)-cnt(p1))) return 0;
if (tl(p2)==tr(p2)) {assert(tr(p2)==pos); return cnt(p2)-cnt(p1);}
int mid=(tl(p2)+tr(p2))>>1;
//cout<<"mid: "<<mid<<endl;
if (pos<=mid) {return query(l(p1), l(p2), pos);}
else return query(r(p1), r(p2), pos);
}
void solve() {
ans=0;
ql=qr=1; q[1].build(INF, 0);
for (int i=1; i<=n; ++i) {
while (ql<=qr && q[qr].val<a[i]) --qr;
l[i]=q[qr].pos+1;
q[++qr].build(a[i], i);
}
ql=qr=1; q[1].build(INF, n+1);
for (int i=n; i; --i) {
while (ql<=qr && q[qr].val<=a[i]) --qr;
r[i]=q[qr].pos-1;
q[++qr].build(a[i], i);
}
//for (int i=1; i<=n; ++i) cout<<l[i]<<' '; cout<<endl;
//for (int i=1; i<=n; ++i) cout<<r[i]<<' '; cout<<endl;
for (int i=1; i<=n+1; ++i) upd(rot[i-1], rot[i], 1, k, sum[i-1]%k+1); //, cout<<"upd: "<<i<<' '<<sum[i-1]%k+1<<endl;
for (int i=1; i<=n; ++i) {
if (l[i]==r[i]) continue;
if (i-l[i]<r[i]-i) {
for (int j=l[i]; j<=i; ++j) {
ans += query(rot[max(j+1, i)], rot[r[i]+1], (sum[j-1]+a[i])%k+1);
//if (sum[i]%k == (sum[r[i]]+a[i])%k) --ans;
//if (i!=j && (sum[j]-a[i])%k==0) ++ans;
//if (i==j && sum[i]%k==(sum[j-1]+a[i])%k) --ans;
#if 0
cout<<"range: "<<j+1<<' '<<r[i]+1<<endl;
cout<<"ask: "<<(sum[j-1]+a[i])%k+1<<endl;
cout<<"i: "<<i<<endl;
cout<<"j: "<<j<<endl;
cout<<"ans: "<<ans<<endl;
cout<<endl;
#endif
}
}
else {
for (int j=i; j<=r[i]; ++j) {
//cout<<"ans: "<<ans<<endl;
ans += query(rot[l[i]+1-1-1], rot[min(i, j-1)], ((sum[j]-a[i])%k+k)%k+1);
//if (sum[i]%k == ((sum[j]-a[i])%k+k)%k) --ans;
//if (i!=j && (sum[j]-a[i])%k==0) ++ans;
#if 0
cout<<"range: "<<l[i]+1-1-1<<' '<<min(i, j-1)<<endl;
cout<<"ask: "<<((sum[j]-a[i])%k+k)%k+1<<endl;
cout<<"i: "<<i<<endl;
cout<<"j: "<<j<<endl;
cout<<"ans: "<<ans<<endl;
cout<<endl;
#endif
}
}
//cout<<i<<": "<<ans<<endl;
}
printf("%lld\n", ans);
}
}
signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif
n=read(); k=read();
for (int i=1; i<=n; ++i) a[i]=read(), sum[i]=sum[i-1]+a[i];
//cout<<"sum: "; for (int i=1; i<=n; ++i) cout<<sum[i]<<' '; cout<<endl;
//force::solve();
task1::solve();
return 0;
}