1. 程式人生 > >2018.10.28 洛谷 進化の水題:模擬賽

2018.10.28 洛谷 進化の水題:模擬賽

傳送門
T 1 T1 一直過不了導致心態爆炸,導致打了不到兩個小時就棄了。
r a n ran

k# 22 22 滾粗。
說到底 A A 了的也只有 T 2
T2
啊。。。
T 1 T1 不知道為什麼答案一直是錯的。
T 5 T5
寫隨機化貪心比暴力多過了 5 p t s 5pts 妙啊
於是先貼一波 T 2 T2 s b sb 線段樹程式碼:

#include<bits/stdc++.h>
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
using namespace std;
const int N=500005;
int n,m;
struct Node{int l,r,cov,col;bool f;}T[N<<2];
char s[N];
inline void pushup(int p){T[p].f=T[lc].f&&T[rc].f&&T[lc].col==T[rc].col,T[p].col=T[lc].col;}
inline void pushnow(int p,int v){T[p].cov=T[p].col=v,T[p].f=1;}
inline void pushdown(int p){if(~T[p].cov)pushnow(lc,T[p].cov),pushnow(rc,T[p].cov),T[p].cov=-1;}
inline void build(int p,int l,int r){
    T[p].l=l,T[p].r=r,T[p].cov=-1;
    if(l==r){T[p].col=s[l]-'A',T[p].f=1;return;}
    build(lc,l,mid),build(rc,mid+1,r),pushup(p);
}
inline void update(int p,int ql,int qr,int v){
    if(ql<=T[p].l&&T[p].r<=qr)return pushnow(p,v);
    pushdown(p);
    if(qr<=mid)update(lc,ql,qr,v);
    else if(ql>mid)update(rc,ql,qr,v);
    else update(lc,ql,mid,v),update(rc,mid+1,qr,v);
    pushup(p);
}
inline pair<bool,int> query(int p,int ql,int qr){
    if(ql>T[p].r||qr<T[p].l)return make_pair(1,-1);
    if(ql<=T[p].l&&T[p].r<=qr)return make_pair(T[p].f,T[p].col);
    pushdown(p);
    if(qr<=mid)return query(lc,ql,qr);
    else if(ql>mid)return query(rc,ql,qr);
    pair<bool,int> a=query(lc,ql,mid),b=query(rc,mid+1,qr);
    return make_pair(a.first&&b.first&&a.second==b.second,a.second);
}
int main(){
    scanf("%d%s%d",&n,s+1,&m),build(1,1,n);
    while(m--){
        char op[2];
        int x,y;
        char z[2];
        scanf("%s",op);
        if(op[0]=='A')scanf("%d%d%s",&x,&y,z),update(1,x,y,z[0]-'A');
        else{
            scanf("%d%d",&x,&y);
            pair<bool,int>a=query(1,x-1,x-1),b=query(1,x,y),c=query(1,y+1,y+1);
            if(b.first&&(a.second==-1||c.second==-1||a.second!=c.second))puts("Yes");
            else puts("No");
        } 
    }
    return 0;
}

u p d : T 1 upd:T1
比賽的時候思路的確是對的二分lower_bound掛了
沒錯就是排序+二分。
直接把第二個陣列的全部區間和處理出來,排個序。
然後列舉第一個陣列的全部區間和,每個拿去 l o w e r b o u n d lower_bound 一下就行了。
然而我的二分邊界一直是錯的233.
程式碼:

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int ans=0;
	char ch=getchar();
	while(!isdigit(ch))ch=getchar();
	while(isdigit(ch))ans=(ans<<3)+(ans<<1)+(ch^48),ch=getchar();
	return ans;
}
typedef long long ll;
const int N=2005;
const ll mod=998244353;
int n,m;
ll val[N*N],a[N],b[N],tot=0,ans=0;
inline ll ksm(ll x,ll p){x%=mod;ll ret=1;for(;p;p>>=1,x=x*x%mod)if(p&1)ret=ret*x%mod;return ret;}
inline ll query(ll v){
	if(val[tot]<v)return tot;
	if(val[1]>=v)return 0;
	int l=1,r=tot,ans=1;
	while(l<=r){
		int mid=l+r>>1;
		if(val[mid]>=v)r=mid-1,ans=mid;
		else l=mid+1;
	}
	while(val[ans]>=v)--ans;
	return (ll)ans;
}
int main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)a[i]=a[i-1]+read();
	for(int i=1;i<=m;++i){
		b[i]=b[i-1]+read();
		for(int j=1;j<=i;++j)val[++tot]=b[i]-b[j-1];
	}
	sort(val+1,val+tot+1);
	for(int l=1;l<=n;++l)for(int r=l;r<=n;++r){
		ll sum=a[r]-a[l-1];
		ans+=query(sum);
		ans%=mod;
	}
	ans=ans*ksm(1ll*n*(n+1)/2ll*(1ll*m*(m+1)/2),mod-2)%mod;
	cout<<ans;
	return 0;
}

其它題目以後有空再更新啦。