题解 简单的区间

传送门

因为把(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;
}
posted @ 2021-07-13 05:59  Administrator-09  阅读(12)  评论(0编辑  收藏  举报