CSP模拟<反思>(35~41)

好久没有写博客了

csp模拟35#

斯坦纳树#

错误做法会使 1,3,4 的情况 edge1>2 算重,所以对于不在点集的点有三条分叉数会使答案不合法。考虑计算个数,记为 cnt ,如果为零则假成真。

倒序删除一些点,假如这个点分叉数大于等于3 ,则 cnt++ ;如果等于2,则将其左右两侧点连边,删除这个点;如果等于一,是会影响其他的在答案内的点,所以递归删除。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=6*1e5+5;
int head[N*2],ver[N*2],nex[N*2],tot=0;
void add(int x,int y){
	ver[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
int du[N];
int x[N],y[N],w[N];
int b[N],a[N];
bool flat[N];
int fa[N],sum[N];
int get_fa(int x){
	if(fa[x]==x) return fa[x];
	else return fa[x]=get_fa(fa[x]);
}
map<int,int>mp[N];
int cnt=0;
bool vis[N];
void dele(int x){
	if(du[x]==1){
		if(flat[x]){
			flat[x]=0;
			cnt--;
		}
		du[x]=0;
		vis[x]=0;
		for(int i=head[x];i;i=nex[i]){
			int y=ver[i];
			if(!vis[y]) continue;
			du[y]--;
			if(flat[y]==1){
				dele(y);
			}
		}
	}
	if(du[x]==2){
		if(flat[x]){
			flat[x]=0;
			cnt--;
		}
		int la=0;
		for(int i=head[x];i;i=nex[i]){
			int y=ver[i];
			if(!vis[y]) continue;
			if(la){
				add(la,y),add(y,la);
			}
			else la=y;
		}
		vis[x]=0;
		du[x]=0;
	}
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) fa[i]=i,sum[i]=1;
	for(int i=1;i<n;i++){
		scanf("%d%d%d",&x[i],&y[i],&w[i]);
		if(w[i]==0){
			int fx=get_fa(x[i]),fy=get_fa(y[i]);
			if(fx!=fy){
				fa[fx]=fy;
				sum[fy]+=sum[fx];
			}
		}
	}
	for(int i=1;i<n;i++){
		int fx=get_fa(x[i]),fy=get_fa(y[i]);
		if(fx!=fy && mp[fx][fy]==0){
			add(fx,fy),add(fy,fx);
			vis[fx]=vis[fy]=1;
			du[fx]++,du[fy]++;
			mp[fx][fy]=mp[fy][fx]=1;
		}
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&b[i]);
	}
	for(int k=n;k>=1;k--){
		if(cnt==0) a[k]=1;
		else a[k]=0;
		int x=get_fa(b[k]);
		if(sum[x]>1){
			sum[x]--;
			continue;
		}
		if(du[x]>=3){
			flat[x]=1;
			cnt++;
		}
		if(du[x]==2){
			int la=0;
			for(int i=head[x];i;i=nex[i]){
				int y=ver[i];
				if(!vis[y]) continue;
				if(la){
					add(la,y),add(y,la);
					break;
				}
				else la=y;
			}
			vis[x]=0;
			du[x]=0;
		}
		if(du[x]==1) dele(x);
	}
	for(int i=1;i<=n;i++){
		cout<<a[i];
	}
}

csp模拟36#

博弈#

首先结论是对于一段异或和为0,则先手必输,但是 1 ^ 2 ^ 3=0 所以用哈希,但我比较弱,瞎搞了一个。然后开一个桶树上求就可以了。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5*1e5+5;
const int M=8*1e6;
bool nprime[M];
int prime[M];
void get_prime(){
	for(int i=2;i<=M-5;i++){
		if(!nprime[i]){
			prime[++prime[0]]=i;
		}
		for(int j=1;j<=prime[0]&&i*prime[j]<=M-5;j++){
			int k=i*prime[j];
			nprime[k]=1;
			if(i%prime[j]==0) break;
		}
	}
}
int g[N];
struct asd{
	int x,y,w;
}a[N];
int n;
int head[N*2],ver[N*2],nex[N*2],edge[N*2],tot=0;
map<int,int>mp;
int ans=0;
void add(int x,int y,int w){
	ver[++tot]=y,nex[tot]=head[x],head[x]=tot,edge[tot]=w;
}
int p[N];
void dfs(int x,int f){
	for(int i=head[x];i;i=nex[i]){
		int y=ver[i];
		if(y==f) continue;
		p[y]=p[x]^edge[i];
		if(p[y]==0) ans++;
		ans+=mp[p[y]];
		mp[p[y]]++;
		dfs(y,x);
	}
}
int C(int x,int y){
	int w=1;
	for(int i=x;i>=1;i--){
		w*=i;
	}
	for(int i=y;i>=1;i--){
		w/=i;
	}
	for(int i=x-y;i>=1;i--){
		w/=i;
	}
	return w;
}
void clear(int x){
	tot=0;
	ans=0;
	for(int i=1;i<=x;i++){
		head[i]=0;
		p[x]=0;
	}
	mp.clear();
}
signed main(){
	get_prime();
	int op1=prime[60],op2=prime[600],op3=prime[6000],op4=prime[10000];
	for(int i=1;i<=N;i++){
		if(i%4==1){
			prime[i]*=op1;
		}
		else if(i%4==2){
			prime[i]*=op2;
		}
		else if(i%4==3){
			prime[i]*=op3;
		}
		else{
			prime[i]*=op4;
		}
	}
	int T;
	scanf("%lld",&T);
	while(T--){
		scanf("%lld",&n);
		for(int i=1;i<n;i++){
			scanf("%lld%lld%lld",&a[i].x,&a[i].y,&a[i].w);
			g[i]=a[i].w;
		}
		sort(g+1,g+n);
		int tot=unique(g+1,g+n)-(g+1);
		for(int i=1;i<n;i++){
			int t=lower_bound(g+1,g+n,a[i].w)-g;
			t++;
			add(a[i].x,a[i].y,prime[t]);
			add(a[i].y,a[i].x,prime[t]);
		}
		dfs(1,0);
		ans=n*(n-1)/2-ans;
	    printf("%lld\n",ans);
		clear(n);
	}
}

跳跃#

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1005;
int dp[N],la[N],a[N],s[N];
int g[N],sum[N];
signed main(){
	int T;
	scanf("%lld",&T);
	while(T--){
		int n,k;
		scanf("%lld%lld",&n,&k);
		s[0]=0;
		for(int i=1;i<=n;i++){
			scanf("%lld",&a[i]);
			s[i]=s[i-1]+a[i];
		}
		int wh=0,mi=0;
		for(int i=1;i<=n;i++){
			la[i]=wh;
			sum[i]=s[i]-s[la[i]];
			if(s[i]<mi){
				mi=s[i];
				wh=i;
			}
//			cout<<sum[i]<<endl;
		}
		memset(dp,0x7f,sizeof(dp));
//1120231587044294
//9187201950435737471
		for(int i=1;i<=n;i++){
			if(s[i]>=0){
				dp[i]=1;
				g[i]=s[i];
			}
		}
		for(int i=2;i<=n;i++){
			for(int j=1;j<=i;j++){
				int x=dp[j];
				int ne=s[i]-s[j];
				if(g[j]+ne+sum[j]*2>=0){
					if(dp[i]>dp[j]+2){
						dp[i]=dp[j]+2;
						g[i]=g[j]+ne+sum[j]*2;
					}
					else if(dp[i]==dp[j]+2 && g[j]+ne+sum[j]*2>g[i]){
						g[i]=g[j]+ne+sum[j]*2;
					}
					continue;
				}
				if(sum[j]<=0) continue;
				ne=-(ne+g[j]);
				int cs=ne/sum[j];
				if(ne%sum[j]) cs++;
				if(cs%2){
					int c=cs+1+dp[j];
					int w=cs*sum[j]+sum[j]+s[i]-s[j];
					if(dp[i]>c){
						dp[i]=c;
						g[i]=g[j]+w;
					}
					else if(dp[i]==c && g[j]+w>g[i]){
						g[i]=g[j]+w;
					}
				} 
				else{
					int c=cs+dp[j];
					int w=cs*sum[j]+s[i]-s[j];
					if(dp[i]>c){
						dp[i]=c;
						g[i]=g[j]+w;
					}
					else if(dp[i]==c && g[j]+w>g[i]){
						g[i]=g[j]+w;
					}
				}
			}
		}
		int ans=0;
		for(int i=1;i<=n;i++){
			int s=k-dp[i];
			if(s<0) continue;
			int cnt=sum[i]*s+g[i];
			ans=max(ans,cnt);
		}
		printf("%lld\n",ans);
	}
}

大陆#

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=60002;
int head[N*2],ver[N],nex[N],tot=0;
void add(int x,int y){
	ver[++tot]=y,nex[tot]=head[x],head[x]=tot;
}
int n,B;
int f[N];
int sd[N],rk[N],cnt=0,st[N],top=0;
void dfs(int x,int fa){
    int mem=top;
	for(int i=head[x];i;i=nex[i]){
		int y=ver[i];
		if(y==fa) continue;
		dfs(y,x);
		f[x]+=f[y];
		if(f[x]>=B){
			f[x]=0;
			sd[++cnt]=x;
			for(int j=mem+1;j<=top;j++){
				rk[st[j]]=cnt;
			}
			top=mem;
		}
	}

	st[++top]=x;
	f[x]++;

	if(f[x]>=B){
		f[x]=0;
		sd[++cnt]=x;
        for(int j=mem;j<=top;j++){
            rk[st[j]]=cnt;
        }
        top=mem;
    }
}
int main(){
	scanf("%d%d",&n,&B);
	for(int i=1;i<n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		add(x,y),add(y,x);
	}
	dfs(1,0);

    if(f[1]) {
        for(int j=1;j<=top;j++){
            rk[st[j]]=cnt;
        }
    }

	printf("%d\n",cnt);
	for(int i=1;i<=n;i++){
		printf("%d ",rk[i]);
	}
	cout<<endl;
	for(int i=1;i<=cnt;i++){
		printf("%d ",sd[i]);
	}
}

排列#

一个神奇的平衡树,对于循环移位直接分裂后互换再合并就可以,考虑他是否可行,维护 tag=0/1 是否存在, mx 树内最大值, mn 树内最小值, pmx 树内次大值 , pmn 树内次小值,存在 pmn/pmx 及存在二元上升序列。 考虑合并:

tag 的更新: 如果 mnl<datart<mxr 可行;如果 pmnl<mxr 可行;如果 mnl<pmxr 可行。

pmn/pmx : 更新这个的前提是 tag=0 ,说一下更新 pmx ,在左子树里找一个最大的小于 max(mxr,datart) 的值,因为 tag=0 ,所以左边区间值单调不增,所以尽量靠左,首先如果左子树存在则递归左子树,其次看根满不满足,最后实在不行再递归右子树。

其他的更新正常,就是更新前要一些值。

我代码 time(0) 种子过不了,大佬如果感兴趣可以帮弱鸡看看哪的问题。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=120005;
int n;
struct tree{
	int l,r,rnd,size,mn,mx,pmn,pmx,tag,data;
}tr[N];
int root,idx=0;
inline void newnode(int &p,int x){
	p=++idx;
	tr[p].l=tr[p].r=0;
	tr[p].rnd=rand()*rand(),tr[p].size=1;
	tr[p].tag=0;
	tr[p].data=tr[p].mx=tr[p].mn=x;
	tr[p].pmn=(1ll<<30);
	tr[p].pmx=-(1ll<<30);
}
int ask_pmn(int p,int v){
	if(!p) return (1ll<<20);
	if(tr[tr[p].r].mx>v) return ask_pmn(tr[p].r,v);
	else if(tr[p].data>v) return tr[p].data;
	else return ask_pmn(tr[p].l,v);
}
int ask_pmx(int p,int v){
	if(!p) return -(1ll<<20);
	if(tr[tr[p].l].mn<v) return ask_pmx(tr[p].l,v);
	else if(tr[p].data<v) return tr[p].data;
	else return ask_pmx(tr[p].r,v);
}
inline void pushdown(int p){
	if(!p) return;
	tr[p].size=tr[tr[p].l].size+tr[tr[p].r].size+1;
	tr[p].mx=max(tr[p].data,max(tr[tr[p].l].mx,tr[tr[p].r].mx));
	tr[p].mn=min(tr[p].data,min(tr[tr[p].l].mn,tr[tr[p].r].mn));
	tr[p].pmn=min(tr[tr[p].l].pmn,tr[tr[p].r].pmn);
	tr[p].pmx=max(tr[tr[p].l].pmx,tr[tr[p].r].pmx);
	tr[p].tag=0;
	tr[p].tag=(tr[tr[p].l].tag | tr[tr[p].r].tag);
	if(tr[tr[p].l].mn<tr[p].data && tr[p].data<tr[tr[p].r].mx) tr[p].tag=1;
	if(tr[tr[p].l].pmn<tr[tr[p].r].mx) tr[p].tag=1;
	if(tr[tr[p].l].mn<tr[tr[p].r].pmx) tr[p].tag=1;
	if(tr[p].tag) return;
//	tr[p].pmn=(1<<30),tr[p].pmx=-(1<<30);
	int wh,v;
	v=min(tr[tr[p].l].mn,tr[p].data);
	if(tr[p].data>v) tr[p].pmn=min(tr[p].pmn,tr[p].data);
	if(tr[p].r && tr[tr[p].r].mx>v){
		wh=ask_pmn(tr[p].r,v);
		tr[p].pmn=min(tr[p].pmn,wh);
	}
	v=max(tr[tr[p].r].mx,tr[p].data);
	if(tr[p].data<v) tr[p].pmx=max(tr[p].pmx,tr[p].data);
	if(tr[p].l && tr[tr[p].l].mn<v){
		wh=ask_pmx(tr[p].l,v);
		tr[p].pmx=max(tr[p].pmx,wh);	
	}
}
inline void split(int p,int v,int &x,int &y){
	if(p==0){
		x=0,y=0;return;
	}
	if(tr[tr[p].l].size+1<=v){
		x=p;
		int xi=0;
		split(tr[p].r,v-tr[tr[p].l].size-1,xi,y);
		tr[p].r=xi;
	}
	else{
		y=p;
		int yi=0;
		split(tr[p].l,v,x,yi);
		tr[p].l=yi;
	}
	pushdown(p);
}
inline int merge(int x,int y){
	if(!x || !y) return x+y;
	if(tr[x].rnd<tr[y].rnd){
		tr[x].r=merge(tr[x].r,y);
		pushdown(x);return x;
	}
	else{
		tr[y].l=merge(x,tr[y].l);
		pushdown(y);return y;
	}
}
void insert(int v,int id){
	int x,y,z;
	split(root,id,x,y);
	newnode(z,v);
	root=merge(merge(x,z),y);
}
void work(int a,int b,int k){
	int x,y,p,q;
	split(root,b,p,q);
//	cout<<tr[p].size<<endl;
	split(p,b-k,y,p);
//	cout<<tr[y].size<<endl;
	split(y,a-1,x,y);
//	cout<<tr[x].size<<' '<<tr[y].size<<' '<<tr[p].size<<' '<<tr[q].size<<endl;
	root=merge(merge(x,p),merge(y,q));
}
signed main(){
	scanf("%lld",&n);
	int k=time(0);
	srand(1694609429);
	tr[0].size=tr[0].data=0;
	tr[0].l=tr[0].r=0;
	tr[0].mn=(1ll<<20);
	tr[0].mx=-(1ll<<20);
	tr[0].pmn=(1ll<<20);
	tr[0].pmx=-(1ll<<20);
	tr[0].rnd=rand()*rand();
	tr[0].tag=0;
	for(int i=1;i<=n;i++){
		int x;
		scanf("%lld",&x);
		insert(x,i);
	}
	int q;
	scanf("%lld",&q);
	for(int i=1;i<=q;i++){
		int x,y,k;
		scanf("%lld%lld%lld",&x,&y,&k);
		work(x,y,k);
//		for(int j=1;j<=idx;j++) cout<<tr[j].data<<' '<<tr[j].l<<' '<<tr[j].r<<endl;
		if(tr[root].tag) printf("YES\n");
		else printf("NO\n");
	}
//	cout<<k<<endl;
}
/*
7
7 5 6 3 4 2 1
5
4 5 1
2 5 2
2 6 3
2 7 3
1 7 4
*/

csp模拟37#

喷泉#

每个数都是以一段连续区间存在,且每次修改会使区间减少,所以直接维护区间的值,左端点右端点。但是当 ai 较小时,区间基本不怎么减少,但是可以发现如果 ai 为整个区间 gcd 因数,就不用修改了。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
struct asd{
    int x,l,r;
};
vector<asd> q,p;
signed main(){
    int n,m;
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=n;i++){
        q.push_back({i,i,i});
    }
    int gcd=1;
    for(int i=1;i<=m;i++){
        int k;
        scanf("%lld",&k);
        if(gcd%k==0) continue;
        int la=0;
        int l,r;
        gcd=q[1].x;
        for(int j=0;j<q.size();j++){
            asd a=q[j];
            int ans=a.x;
            if(a.x%k) ans=k*(a.x/k+1);
            if(la==0){
                la=ans;
                l=a.l;r=a.r;
                continue;
            }
            if(ans==la){
                r=a.r;
            }
            else{
            	gcd=__gcd(gcd,la);
                p.push_back({la,l,r});
            	la=ans;
            	l=a.l,r=a.r;
            }
        }
        if(la){
            gcd=__gcd(gcd,la);
        	p.push_back({la,l,r});
		}
        q.clear();
        for(int j=0;j<p.size();j++){
            q.push_back(p[j]);
        }
        p.clear();
    }
    for(int i=0;i<q.size();i++){
        asd a=q[i];
        for(int j=a.l;j<=a.r;j++){
            printf("%lld ",a.x);
        }
    }
}
/*
6 2
3 2
*/

佛怒火莲#

我解释一下最后的方程:首先 dpi 存的是那 32 种情况哪一种合法,对应每一个长度为 5 的 01 串。tpj 是在只有距离限制情况下可以转移到 i 的全部情况,但这些情况不可以包含第 i 种颜色。考虑在这些情况里加入 coli ,会使长度为 5 的 01 串的值加上 (1<<coli) ,即情况排名加上 (1<<coli) ,所以对应到 dpi 中就是左移。

点击查看代码
#include<bits/stdc++.h>
#define ui unsigned int
#define N 10010
using namespace std;

struct NUM{
	int a,b,bs;
}num[N];

bool cmp(NUM x,NUM y){
	return x.b<y.b;
}

map<int,int>col;

inline int Rand(int k){
	return rand()%k;
}
 
int n,k,tp;

ui f[N],ok[6];
ui po[35];

void init(){
	srand(time(0));
	po[0]=1;
	for(int i=1;i<=31;i++) po[i]=po[i-1]*2;
	for(int i=0;i<=31;i++){
		if(i%2<1) ok[0]+=po[i];
		if(i%4<2) ok[1]+=po[i];
		if(i%8<4) ok[2]+=po[i];
		if(i%16<8) ok[3]+=po[i];
		if(i%32<16) ok[4]+=po[i];
	}
}

bool check(int mid,int n){
	f[0]=1;
	int la=0;
	for(int i=1;i<=n;i++){
		while(num[i].b-num[la+1].b>=mid&&la+1<=n) la++;
		int cols=col[num[i].a];
		f[i]=f[i-1]|((f[la]&ok[cols])<<po[cols]);
	}
	if(f[n]&po[po[k]-1]) return 1;
	return 0;
}

int main(){
	init();
	int T;
	scanf("%d",&T);
	while(T--){
		scanf("%d%d%d",&n,&k,&tp);
		for(int i=1;i<=n;i++) scanf("%d%d",&num[i].a,&num[i].b);
		sort(num+1,num+n+1,cmp);
		int ans=0;
		for(int ps=1;ps<=200;ps++){
			col.clear();
			for(int i=1;i<=n;i++)
				if(col.find(num[i].a)==col.end()) col[num[i].a]=Rand(k);
			int l=1,r=num[n].b,lans=1;
			while(l<=r){
				int mid=(l+r)>>1;
				if(check(mid,n)) lans=mid,l=mid+1;
				else r=mid-1;
			}
			ans=max(ans,lans);
		}
		printf("%d\n",ans);
	}
}

csp模拟38#

我是A题#

真是服了,好好一个题怎么恶心的时间空间,自家oj的评测机真是欠修理。

考虑 z 从大到小时计算每层的剩下的值,割去的一定是一个阶梯状的图形,考虑到每一层,新增加的就是两条线割剩下的,且这两条线从上到下递增,维护阶梯图形前缀和计算就可以。

点击查看代码
%:pragma GCC optimize(3)
%:pragma GCC optimize("Ofast")
%:pragma GCC optimize("inline")
#include<bits/stdc++.h>
#define max(x,y) (x)>(y)?(x):(y)
#define rg register 
using namespace std;
const int N = 3e7 + 1;
typedef unsigned long long ull;
int n, A, B, C;
struct asd{
	int x,y,z;
}a[N];
inline ull Rand (rg ull &k1, rg ull &k2) {
 	ull k3 = k1, k4 = k2;
 	k1 = k4;
 	k3 ^= (k3 << 23);
 	k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
 	return k2 + k4;
}

inline void print(__int128 x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) print(x/10);
	putchar(x%10+48);
}
inline bool amp(const asd &a,const asd &b){
	return a.z>b.z;
}
inline int Mod(ull x,int p){
	return x<p?x:x%p;
}
void GetData () {
 	ull x, y;
 	scanf("%d%d%d%d%llu%llu",&n,&A,&B,&C,&x,&y);
 	for (int i = 1; i <= n; ++i) {
 		a[i].x = Mod(Rand(x, y) , A) + 1;
 		a[i].y = Mod(Rand(x, y) , B) + 1;
 		a[i].z = Mod(Rand(x, y) , C) + 1;
 		if (Rand(x, y) % 3 == 0) a[i].x = A;
 		if (Rand(x, y) % 3 == 0) a[i].y = B;
 		if ((a[i].x != A) && (a[i].y != B)) a[i].z = C;
 	}
}
int ma[N];
__int128 sma[N];
int mb[N];
__int128 smb[N];
int la[N],lb[N]; 
signed main(){
	GetData();
	__int128 r=1;//r*
	rg int h=a[1].z;
	rg int tp=0;
	for(rg int i=1;i<=n;++i){
		h=max(h,a[i].z); 
		if(a[i].x==A) lb[a[i].z]=max(lb[a[i].z],a[i].y);
		if(a[i].y==B) la[a[i].z]=max(la[a[i].z],a[i].x);
	} 
	for(int i=1;i<=n;i++){
		if(a[i].z==h){
			ma[a[i].x]=max(ma[a[i].x],a[i].y);
			mb[a[i].y]=max(mb[a[i].y],a[i].x);
		}
	}
	__int128 ans=0;
	__int128 sma1=0;
	for(rg int i=A;i;--i){
		ma[i]=max(ma[i],ma[i+1]);
		sma1=sma1+r*ma[i];
	}
	for(rg int i=B;i;--i){
		mb[i]=max(mb[i],mb[i+1]);
	}
	__int128 sma=0,smb=0;
	ans+=r*A*B-sma1;
	rg int sa=0,sb=0;
	for(rg int i=h-1;i;--i){
		if(sa<=la[i]){
			for(int j=sa+1;j<=la[i];j++){
				sma=sma+r*ma[j];
			}
			sa=la[i];
		}
		if(sb<=lb[i]){
			for(int j=sb+1;j<=lb[i];j++){
				smb=smb+r*mb[j];
			}
			sb=lb[i];
		}
		__int128 op;
		if(sb==0) op=1;
		else op=sb;
		if(mb[op]<sa){
			ans+=r*(A-sa)*(B-sb);
		}
		else{
			__int128 s1=r*A*sb-smb;//(smb[1]-smb[sb+1]);
			__int128 s2=r*B*sa-sma;//(sma[1]-sma[sa+1]);
			ans+=r*A*B-sma1-s1-s2; 
		}
	}
	__int128 uk=r*A*B*C-ans-r*A*B*(C-h);
	print(uk);
}
/* 
100 99 98 97 114514 1919810

2 10 10 10 114514 1919810

1000 43112 88371 27391 114514 1919810
104349748515623

9 7 10
7 10 3
*/

我是B题#

考试只会状压。

dp[i][j] 表示到第 i 个机器时,目标物品排名为 j 的概率。

这里采用刷表法好写一点:

枚举质量为 rnk 的物品;

初始值 dp[1][rnk]=1

转移方程:

dp[i+1][j1]+=dp[i][j]×(1(1pi)j1) //删除的是 j 前面的数,不可能让 j 前面的数全部逃掉

dp[i+1][j]+=dp[i][j]×(1pi)j //删除的是 j 后面的数,jj 前面的数必须全部逃掉

答案 rnk=1ndp[n][1]×rnk

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int mod=1e9+7;
int mgml(int x,int p){
	x=(x+mod)%mod;
	int ans=1;
	while(p){
		if(p&1) ans=(ans*x)%mod;
		x=(x*x)%mod;
		p>>=1;
	}
	return ans;
}
int dp[305][305];
int p[305];
int n;
int work(int d){
	memset(dp,0,sizeof(dp));
	dp[0][d-1]=1;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(dp[i][j]==0) continue;
			dp[i+1][j]+=dp[i][j]*mgml(1-p[i+1],j+1)%mod;
			dp[i+1][j]%=mod;
			if(j>0) dp[i+1][j-1]+=(dp[i][j]*(1-mgml(1-p[i+1],j)+mod)%mod)%mod;
			if(j>0) dp[i+1][j-1]%=mod;
		}
	}
	return dp[n-1][0];
}
signed main(){
	scanf("%lld",&n);
	for(int i=1;i<n;i++){
		scanf("%lld",&p[i]);
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		int d=work(i);
		ans+=i*d%mod;
		ans%=mod;
	}
	printf("%lld",ans);
}

我是C题#

首先一次找出所有出现次数较小的数字比较耗时,我们可以找到任意一个出现次数不满足要求的数字,并且从这个数字处把区间分成两半进行递归,并不会影响正确性,还大大降低了编程复杂度。

但是由于分治两边可能不均等,会导致时间复杂度退化成 O(n2) ,维护 cnti 表示 i 出现的次数。所以选择只遍历小的区间。第一遍删去小区间的值,然后递归大区间,第二遍加上小区间的值递归小区间,不合法的区间以及合法的区间统计完后记得删去 cnt

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int a[N],b[N];
int cnt[N],d[N];
int ans=0;
void solve(int l,int r){
	if(r-l+1<b[r-l+1]){
		for(int i=l;i<=r;i++){
			cnt[a[i]]--;
		}
		return;
	}
	if(l==r){
		if(b[1]<=1) ans=max(ans,ans);
		cnt[a[l]]--;
		return;
	}
	int mid=(l+r)/2;
	int pos=-1,k=b[r-l+1];
	for(int i=l;i<=r;i++){
		if(cnt[a[i]]<k){
			pos=i;
			break;
		}
	}
	if(pos==-1){
		for(int i=l;i<=r;i++) cnt[a[i]]--;
		ans=max(ans,r-l+1);
		return;
	}
	if(pos<=mid){
		for(int i=l;i<=pos;i++) cnt[a[i]]--;
		solve(pos+1,r);
		for(int i=l;i<pos;i++) cnt[a[i]]++;
		solve(l,pos-1);
	}
	else{
		for(int i=pos;i<=r;i++) cnt[a[i]]--;
		solve(l,pos-1);
		for(int i=pos+1;i<=r;i++) cnt[a[i]]++;
		solve(pos+1,r);
	}
}
int main(){
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
		cnt[a[i]]++;
	}
	for(int i=1;i<=n;i++){
		scanf("%d",&b[i]);
	}
	solve(1,n);
	cout<<ans<<endl;
} 

csp模拟39#

钱仓#

(a+b)2>a2+b2 所以可以破环成链,枚举每一个起点 进行计算,假设向后转移完值大于等于2,则不合法。O(n2)

考虑起点是不是可以求出,每一个合法的情况的值都是固定的吗?(谁理解给我讲讲,反正我没听),起点为最大子段和的起点。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=3*1e5+5;
int n;
int a[N];
int b[N];
long long ans=(1ll<<50);
int st[N];
long long check(int x){
	int k=0;
	for(int i=x;i<=x+n-1;i++){
		b[i-x+1]=a[i];
		k+=a[i];
		if(k<i-x+1) return (1ll<<50);
	}
	long long sum=0;
	int head=0,tail=0;
	for(int i=n;i>=1;i--){
		if(b[i]==0) st[++tail]=i;
		else{
			int tmp=b[i];
			while(tmp && head+1<=tail){
				int wh=++head;
				sum+=(st[head]-i)*(st[head]-i);
				tmp--;
			}
			if(tmp>1) return (1ll<<50);
			if(tmp==0) st[++tail]=i;
		}
	}
	return sum;
}
int sum[N];
signed main(){
	freopen("barn.in","r",stdin);
	freopen("barn.out","w",stdout);
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		scanf("%lld",&a[i]);
		a[n+i]=a[i];
		sum[i]=sum[i-1]+a[i]-1;
	}
	for(int i=n+1;i<=n*2;i++){
		sum[i]=sum[i-1]+a[i]-1;
	}
	int ma=-1;
	int id=0,st;
	for(int i=1;i<=n*2;i++){
		if(sum[i]-sum[id]>=ma){
			st=id;
			ma=sum[i]-sum[id];
		}
		if(sum[id]>=sum[i] && i<=n){
			id=i;
		}
	}
	ans=check(st+1);
	cout<<ans;
	cerr<<st+1<<endl;
}

CSP模拟40联测2#

全是诈骗!!

地理课#

前置知识: 线段树分治

一种离线处理方法

可以处理“具体哪个修改对询问有影响”、可以贡献不独立、可以支持插入删除。

对这道题来说,对修改开线段树,线段树上每个节点开一个 vector 来维护出现在这段区间的线段,加入一个线段的区间,直接在区间查询时对所包含的节点压入这条线段就可以。

然后从根节点递归,先左子树再右子树,对途中经过的结点上的线段计算答案,这里用不压缩路径的并查集维护。对于加入,只需要将个数小的合并到个数多的(启发式合并),只需要将祖先的父亲和大小更改,所以开一个栈维护这个操作,对于删除就是将祖先更改过来。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
const int mod=1e9+7;
struct asd{
	int op,x,y;
}a[N],b[N];
struct tree{
	int l,r;
}tr[N*4];
struct qwe{
	int x,y,sizx,sizy;
}st[N];
int top=0;
vector<int> s[N*4];
map<int,int> mp[N],rk[N];
int cnt=0;
int mgml(int x,int p){
	int ans=1;
	while(p){
		if(p&1) ans=(ans*x)%mod;
		x=(x*x)%mod;
		p>>=1;
	}
	return ans;
}
void build(int p,int l,int r){
	tr[p].l=l,tr[p].r=r;
	if(l==r) return;
	int mid=(l+r)/2;
	build(p*2,l,mid);
	build(p*2+1,mid+1,r);
}
void change(int p,int l,int r,int v){
	if(tr[p].l>=l && tr[p].r<=r){
		s[p].push_back(v);
		return;
	}
	int mid=(tr[p].l+tr[p].r)/2;
	if(l<=mid) change(p*2,l,r,v);
	if(r>mid) change(p*2+1,l,r,v);
}
int fa[N];
int sum[N];
int get_fa(int x){
	if(fa[x]==x) return x;
	else return get_fa(fa[x]);
}
int ans=1;
int anss[N];
void add(int p){
	for(int i=0;i<s[p].size();i++){
		int id=s[p][i];
		int x=b[id].x,y=b[id].y;
		int fx=get_fa(x),fy=get_fa(y);
		if(fx==fy) continue;
		if(sum[fx]>sum[fy]) swap(fx,fy);
		st[++top]={fx,fy,sum[fx],sum[fy]};
		fa[fx]=fy;
		ans=ans*(sum[fx]+sum[fy])%mod*mgml(sum[fx]*sum[fy]%mod,mod-2)%mod;
		ans%=mod;
		sum[fy]+=sum[fx];
	}
}
void dele(int now,int p){
	while(top>now){
		int x=st[top].x,y=st[top].y;
		int sizx=st[top].sizx,sizy=st[top].sizy;
		ans=ans*sizx%mod*sizy%mod*mgml((sizx+sizy)%mod,mod-2)%mod;
		ans%=mod;
		fa[x]=x,fa[y]=y;
		sum[x]=sizx,sum[y]=sizy;
		top--;
	}
}
void dfs(int p){
	int now=top;
	add(p);
	if(tr[p].l==tr[p].r){
		anss[tr[p].l]=ans;
	}
	else{
		dfs(p*2),dfs(p*2+1);
	}
	dele(now,p);
} 
signed main(){
	int n,m;
	scanf("%lld%lld",&n,&m);
	for(int i=1;i<=n;i++){
		fa[i]=i;
		sum[i]=1;
	}
	build(1,1,m);
	for(int i=1;i<=m;i++){
		scanf("%lld%lld%lld",&a[i].op,&a[i].x,&a[i].y);
		if(rk[a[i].x][a[i].y]==0){
			rk[a[i].x][a[i].y]=rk[a[i].x][a[i].y]=++cnt;
			b[cnt].x=a[i].x,b[cnt].y=a[i].y;
		}
	}
	for(int i=1;i<=m;i++){
		if(a[i].op==1){
			mp[a[i].x][a[i].y]=mp[a[i].y][a[i].x]=i;
		}
		else{
			int st=mp[a[i].x][a[i].y];
			mp[a[i].x][a[i].y]=mp[a[i].y][a[i].x]=0;
			change(1,st,i-1,rk[a[i].x][a[i].y]);
		}
	}
	for(int i=1;i<=m;i++){
		if(mp[a[i].x][a[i].y]){
			int st=mp[a[i].x][a[i].y];
			mp[a[i].x][a[i].y]=mp[a[i].y][a[i].x]=0;
			change(1,st,m,rk[a[i].x][a[i].y]);
		}
	}
	dfs(1);
	for(int i=1;i<=m;i++){
		cout<<anss[i]<<endl;
	}
}

CSP模拟41联测3#

超级加倍#

建两棵树 T1,T2, 第一课树从跟到叶子逐渐递减,第二棵从跟到叶子逐渐递增。

考虑怎么建,以第一棵为例,从 1b 枚举,每个点找它直接与它相连的点,如果还没加入那就不管,否则找到它的祖先,与其连边,将它的祖先设为自己。

然后就变成求点对 (x,y) 在第一棵树中 xy 祖先,在第二棵树中 yx 祖先的个数

得到有第一棵树的 dfs 序,然后开始遍历第二棵树,将遍历到的点加入树状数组中,遍历到 x 点,查询第一棵树中 x 的子树中存在点的个数,计算贡献。

点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2*1e6+5;
int a[N];
int n;
int head_1[N*2],ver_1[N*2],nex_1[N*2],tot_1=0;
void add_1(int x,int y){
	ver_1[++tot_1]=y,nex_1[tot_1]=head_1[x],head_1[x]=tot_1;
}
int head_2[N*2],ver_2[N*2],nex_2[N*2],tot_2=0;
void add_2(int x,int y){
	ver_2[++tot_2]=y,nex_2[tot_2]=head_2[x],head_2[x]=tot_2;
}
int head_3[N*2],ver_3[N*2],nex_3[N*2],tot_3=0;
void add_3(int x,int y){
	ver_3[++tot_3]=y,nex_3[tot_3]=head_3[x],head_3[x]=tot_3;
}
int fa[N];
int get_fa(int x){
	if(fa[x]==x) return x;
	else return fa[x]=get_fa(fa[x]);
}
int id[N],cnt=0,rk[N],size[N];
void dfs_1(int x,int f){
	id[x]=++cnt;
	rk[cnt]=x;
	size[x]=1;
	for(int i=head_2[x];i;i=nex_2[i]){
		int y=ver_2[i];
		if(y==f) continue;
		dfs_1(y,x);
		size[x]+=size[y];
	}
}
int c[N];
int lowbit(int x){
	return x&(-x);
}
void add(int x,int v){
	for(;x<=n;x+=lowbit(x)) c[x]+=v;
	return;
}
int ask(int x){
	if(x==0) return 0;
	int ans=0;
	for(;x;x-=lowbit(x)) ans+=c[x];
	return ans;
}
int ans=0;
void dfs_2(int x,int f){
	ans+=ask(id[x]+size[x]-1)-ask(id[x]-1);
	add(id[x],1);
	for(int i=head_3[x];i;i=nex_3[i]){
		int y=ver_3[i];
		if(y==f) continue;
		dfs_2(y,x);
	}
	add(id[x],-1);
}
signed main(){
	scanf("%lld",&n);
	for(int i=1;i<=n;i++){
		fa[i]=i;
		int x;
		scanf("%lld",&x);
		if(x==0) continue;
		add_1(x,i);add_1(i,x);
	}
	for(int x=1;x<=n;x++){
		for(int i=head_1[x];i;i=nex_1[i]){
			int y=ver_1[i];
			if(y<x){
				int fy=get_fa(y);
				add_2(x,fy),add_2(fy,x);
				fa[fy]=x;
			}
		}
	}
	dfs_1(n,0);
	for(int i=1;i<=n;i++) fa[i]=i;
	for(int x=n;x>=1;x--){
		for(int i=head_1[x];i;i=nex_1[i]){
			int y=ver_1[i];
			if(y>x){
				int fy=get_fa(y);
				add_3(x,fy),add_3(fy,x);
				fa[fy]=x;
			}
		}
	}
	dfs_2(1,0);
	cout<<ans<<endl;
}
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5*1e5+5;
int n,ls,rs;
struct asd{
    int x,v;
}a[N];
struct qwe{
    int t,x,y;
}c[N],b[N];
int t1,t2;
int tp=0,tp1=0;
int check(int d){
    int ans=0;
    int p=0;
    a[0].x=-(1ll<<50);
    int sum=0;
    int pos=0;
    while(pos<=n){
        while(a[pos].v!=-1){
            pos++;
            if(a[pos].v==1) sum++;
        }
        while(a[pos].x-a[p].x>d){
            if(a[p].v==1) sum--;
            p++;
        }
        ans+=sum;
        pos++;
        if(a[pos].v==1) sum++;
    }
    return ans;
}
set<int> s;
void work(){
	s.clear();
    int p1=0,p2=0;
    int sum=0;
    int pos=0;
    while(pos<=n){
    	while(a[pos].v!=-1){
    		pos++;
    		if(a[pos].v==1) sum++;
		}
		while(a[p2+1].x+t1<=a[pos].x){
			p2++;
			if(a[p2].v==1) s.insert(p2);
		}
		while(a[p1+1].x+t2<=a[pos].x){
			if(a[p1].v==1 && sum) sum--,s.erase(s.find(p1));
			p1++;
		}
		set<int>::iterator it;
		int cnt=0;
		if(sum){
			for(it=s.begin();it!=s.end();it++){
				b[++tp].t=a[pos].x-a[*it].x;
				int id=sum-cnt;
				cnt++;
				b[tp].x=pos-id,b[tp].y=pos-(id-1);
			}	
		}
		pos++;
		if(a[pos].v==1) sum++;
	}
}
void work1(int d){
	s.clear();
	int p1=0,p2=0;
    int sum=0;
    int pos=0;
    while(pos<=n){
    	while(a[pos].v!=-1){
    		pos++;
    		if(a[pos].v==1) sum++;
		}
		while(a[p2+1].x+d<=a[pos].x){
			p2++;
			if(a[p2].v==1) s.insert(p2);
		}
		while(a[p1+1].x+d<=a[pos].x){
			if(a[p1].v==1 && sum) sum--,s.erase(s.find(p1));
			p1++;
		}
		set<int>::iterator it;
		int cnt=0;
		if(sum){
			for(it=s.begin();it!=s.end();it++){
				b[++tp].t=a[pos].x-a[*it].x;
				int id=sum-cnt;
				cnt++;
				b[tp].x=pos-id,b[tp].y=pos-(id-1);
			}	
		}
		pos++;
		if(a[pos].v==1) sum++;
	}
}
bool amp(asd a,asd b){
    return a.x<b.x;
}
bool bmp(qwe a,qwe b){
    if(a.t==b.t){
        if(a.x==b.x) return a.y<b.y;
        else return a.x<b.x;
    }
    else return a.t<b.t;
}
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++) scanf("%lld%lld",&a[i].x,&a[i].v);
    sort(a+1,a+n+1,amp);
    scanf("%lld%lld",&ls,&rs);
//    for(int i=0;i<=40;i++){
//    	cout<<i<<":  "<<check(i)<<endl;
//	}
    int l=0,r=N;
    while(l<r){
        int mid=(l+r)/2;
        if(check(mid)>=ls) r=mid;
        else l=mid+1;
    }
    t1=l;
    l=0;r=N;
    while(l<r){
        int mid=(l+r)/2;
        if(check(mid)>=rs) r=mid;
        else l=mid+1;
    }
    t2=l;
    if(check(t2)>rs) t2--;
//    cout<<t1<<"          "<<t2<<endl;
    work();
    int sum1=ls-check(t1-1)-1;
    if(sum1>0){
    	tp1=0;
	    work1(t1-1);
	    sort(c+1,c+tp1+1,bmp);
	    for(int i=tp1;i>=tp1-sum1+1;i--){
	        b[++tp].t=c[i].t,b[tp].x=c[i].x,b[tp].y=c[i].y;
	    }	
	}
    int sum2=rs-check(t2);
    if(sum2>0){
	    work1(t2+1);
	    tp1=0;
	    sort(c+1,c+tp1+1,bmp);
	    for(int i=1;i<=sum2;i++){
	        b[++tp].t=c[i].t,b[tp].x=c[i].x,b[tp].y=c[i].y;
	    }	
	}
    sort(b+1,b+tp+1,bmp);
    for(int i=1;i<=tp;i++){
        cout<<b[i].x<<" "<<b[i].y<<endl;
    }
}





#include<bits/stdc++.h>
#define N 300010

using namespace std;

struct points{
	long long posi,v;
	long long id;
}pi[N];

bool cmp(points a,points b){
	return a.posi<b.posi;
}

long long s[N],n;

long long work(long long mid){
	long long sum=0,an=0;
	long long l=1;
	for(long long i=1;i<=n;i++){
		if(pi[i].v==1) sum++;
		else{
			while(pi[i].posi-pi[l].posi>mid){
				if(pi[l].v==1) sum--;
				l++;
			}
			an+=sum;
		}
	}
	return an;
}

struct three{
	long long x,y,t;
}pa[N];

bool cmps(three a,three b){
	if(a.t!=b.t) return a.t<b.t;
	if(a.x!=b.x) return a.x<b.x;
	if(a.y!=b.y) return a.y<b.y;
}

pair<long long,long long>ps[N],ans[N];
long long tot=0,all=0;

int main(){
//	freopen("collision4.in","r",stdin);
//	freopen("out.txt","w",stdout);
	long long l,r;
	scanf("%lld",&n);
	s[0]=0;
	for(long long i=1;i<=n;i++){
		scanf("%lld%lld",&pi[i].posi,&pi[i].v);
		pi[i].id=i;
		s[i]=s[i-1];
		if(pi[i].v==-1) s[i]++;
	}
	sort(pi+1,pi+n+1,cmp);
	scanf("%lld%lld",&l,&r);
	
//	for(int i=0;i<=40;i++){
//		cout<<i<<" "<<work(i)<<endl;
//	}
//	return 0;
	long long ls=0,rs=2e9+1,lans,anss;
	while(ls<=rs){
		long long mid=(ls+rs)>>1;
		anss=work(mid);
		if(anss>=l) lans=mid,rs=mid-1;
		else ls=mid+1;
	}
	anss=work(lans);
	long long p=n;
	for(long long i=n;i>=1;i--){
		while(pi[p].posi-pi[i].posi>lans) p--;
		if(pi[p].v==-1&&pi[i].v==1&&pi[p].posi-pi[i].posi==lans) ps[++tot]={pi[i+s[p-1]-s[i-1]].id,pi[i+s[p-1]-s[i-1]+1].id};
	}
	sort(ps+1,ps+tot+1);
	anss=anss-l+1;
	for(long long i=tot-anss+1;i<=tot;i++) ans[++all]=ps[i];
	
	ls=0,rs=2e9+1;
	long long rans;
	while(ls<=rs){
		long long mid=(ls+rs)>>1;
		anss=work(mid);
		if(anss>=r) rans=mid,rs=mid-1;
		else ls=mid+1;
	}
	work(rans);
	
	if(rans==lans) all=r-l+1;
	else{
		p=n;
		tot=0;
		for(long long i=n;i>=1;i--){
			while(pi[p].posi-pi[i].posi>rans) p--;
			long long pp=p;
			while(pi[pp].posi-pi[i].posi>lans){
				if(pi[pp].v==-1&&pi[i].v==1) pa[++tot]={pi[i+s[pp-1]-s[i-1]].id,pi[i+s[pp-1]-s[i-1]+1].id,pi[pp].posi-pi[i].posi};
				pp--;
			}
		}
		sort(pa+1,pa+tot+1,cmps);
		for(long long i=1;all<r-l+1;i++){
			all++;
			ans[all].first=pa[i].x;
			ans[all].second=pa[i].y;
		}
	}
	for(long long i=1;i<=all;i++) printf("%lld %lld\n",ans[i].first,ans[i].second);
	return 0;
}



*/
点击查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5*1e5+5;
int n,ls,rs;
struct asd{
    int x,v;
}a[N];
struct qwe{
    int t,x,y;
}b[N],ans[N],c[N];
int tp=0;
int t1,t2;
int check(int d){
    int ans=0;
    int p=0;
    a[0].x=-(1ll<<50);
    int sum=0;
    int pos=0;
    while(pos<=n){
        while(a[pos].v!=-1 && pos<=n){
            pos++;
            if(a[pos].v==1) sum++;
        }
        if(pos>n) break;
        while(a[pos].x-a[p].x>d){
            if(a[p].v==1) sum--;
            p++;
        }
        ans+=sum;
        pos++;
        if(a[pos].v==1) sum++;
    }
    return ans;
}
bool bmp(qwe a,qwe b){
    if(a.t==b.t){
        if(a.x==b.x) return a.y<b.y;
        else return a.x<b.x;
    }
    else return a.t<b.t;
}
int s[N];
signed main(){
    scanf("%lld",&n);
    for(int i=1;i<=n;i++){
		scanf("%lld%lld",&a[i].x,&a[i].v);
    	s[i]=s[i-1]+(a[i].v==-1);
	}
    scanf("%lld%lld",&ls,&rs);
//    for(int i=0;i<=30;i++){
//    	cout<<i<<":  "<<check(i)<<endl;
//	}
//	return 0;
    int l=0,r=2e9+10;
    while(l<r){
        int mid=(l+r)/2;
        if(check(mid)>=ls) r=mid;
        else l=mid+1;
    }
    t1=l;
    int anss=check(t1);
    int p=n;
    for(int i=n;i>=1;i--){
    	while(a[p].x-a[i].x>t1) p--;
    	if(a[p].v==-1 && a[i].v==1 && a[p].x-a[i].x==t1){
    		b[++tp]={t1,i+s[p-1]-s[i-1],i+s[p-1]-s[i-1]+1};
		}
	}
	sort(b+1,b+tp+1,bmp);
	anss=anss-ls+1;
	int all=0;
	for(int i=tp-anss+1;i<=tp;i++){
		ans[++all]=b[i];
	}
    l=0;r=2e9+10;
    while(l<r){
        int mid=(l+r)/2;
        if(check(mid)>=rs) r=mid;
        else l=mid+1;
    }
    t2=l;
//    cout<<t1<<"   "<<t2<<endl;
    if(t1==t2) all=rs-ls+1;
    else{
    	p=n;
    	tp=0;
    	for(int i=n;i>=1;i--){
    		while(a[p].x-a[i].x>t2) p--;
    		int pp=p;
    		while(a[pp].x-a[i].x>t1){
    			if(a[pp].v==-1 && a[i].v==1){
    				c[++tp]={a[pp].x-a[i].x,i+s[pp-1]-s[i-1],i+s[pp-1]-s[i-1]+1};
				}
				pp--;
			}
		}
		sort(c+1,c+tp+1,bmp);
		for(int i=1;all<rs-ls+1;i++){
			ans[++all]=c[i];
		}
	}
	for(int i=1;i<=all;i++){
		cout<<ans[i].x<<" "<<ans[i].y<<endl;
	}
}
/*
4
1 1
2 1
3 -1
4 -1
2 4
*/ 

作者:bloss

出处:https://www.cnblogs.com/jinjiaqioi/p/17703576.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   _bloss  阅读(50)  评论(1编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu