Brief Solutions to [BJOI 2019 Day2]

Posted by JP128 on Thu, 05 Sep 2019 09:39:21 +0200

I feel that the difficulty of 2 days is not in one grade.

T1:

Portal

Very popular -
Discrete O(n3)O(n^3)O(n3) knapsack is enough

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
cs int N=205,M=40005;
int f[N][M];
pii opt[N];
int s,n,m;
int inf;
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
vector<int> a[N];
int main(){
	s=read(),n=read(),m=read();
	for(int i=1;i<=s;i++){
		for(int j=1;j<=n;j++)a[j].pb(read()*2+1);
	}
	for(int i=1;i<=n;i++)a[i].pb(0),sort(a[i].bg(),a[i].end());
	memset(f,128,sizeof(f));
	f[0][0]=0;
	for(int i=1;i<=n;i++){
		for(int j=0;j<a[i].size();j++){
			int v=a[i][j];
			for(int k=v;k<=m;k++)
			chemx(f[i][k],f[i-1][k-v]+j*i);
		}
	}
	int res=0;
	for(int i=0;i<=m;i++)chemx(res,f[n][i]);
	cout<<res;
}

T2:

Obviously it should be something that sums up an equal-ratio sequence.
f[i]f[i]f[i] denotes how much light will be reflected from the direction of the i+1i+1i+1 glass to the iii glass.
Calculate it by hand.
f[i]=b[i]+a[i]2f[i−1]1−f[i−1]b[i]f[i]=b[i]+\frac{a[i]^2f[i-1]}{1-f[i-1]b[i]}f[i]=b[i]+1−f[i−1]b[i]a[i]2f[i−1]​
Let v[i]v[i]v[i] express the total amount of light that can be emitted from the direction of block i_1i-1i_1 to block iii.
Let's get v[i]=a[i]1 f[i 1] B [i] V [i]= frac {a [i]} {1-f[i-1] B [i]} V [i]= 1 f[i 1]b[i]a[i]

And then it's over.

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
const int mod=1e9+7;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline void Add(int &a,int b){a=add(a,b);}
inline int dec(int a,int b){return a>=b?a-b:a-b+mod;}
inline void Dec(int &a,int b){a=dec(a,b);}
inline int mul(int a,int b){return 1ll*a*b%mod;}
inline void Mul(int &a,int b){a=mul(a,b);}
inline int ksm(int a,int b,int res=1){for(;b;b>>=1,a=mul(a,a))(b&1)?(res=mul(res,a)):0;return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
inline int P(int x){return mul(x,x);}
cs int N=500005;
cs int Iv=Inv(100);
int n,A[N],B[N],f[N],v[N];
int main(){
	n=read();
	for(int i=1;i<=n;i++)A[i]=mul(read(),Iv),B[i]=mul(read(),Iv);
	for(int i=1;i<=n;i++){
		f[i]=add(B[i],mul(mul(P(A[i]),f[i-1]),Inv(dec(1,mul(f[i-1],B[i])))));
	}
	for(int i=1;i<=n;i++)v[i]=mul(A[i],Inv(dec(1,mul(f[i-1],B[i]))));
	int res=1;
	for(int i=1;i<=n;i++)Mul(res,v[i]);
	cout<<res;
}

T3:

Obviously, the condition for discovery to be deleted is
For each value vvv, the number less than or equal to VVV happens to have VVV
But it's not easy to maintain.
Consider if there are kkk vvv s
In fact, it can be seen as covering [v_k+1,v][v-k+1,v][v_k+1,v] to 111.
The final requirement is the number of points in 000.
Quantity can be maintained by opening a bucket.

Then use the weighted line segment tree to do it.

So the modification is well maintained.
Just add and subtract one point.
Consider total addition and subtraction
You can remember where you started.

If a certain number is greater than nnn, delete its coverage of a paragraph on the left
Wait less than or equal to nnn and come back

This requires maintaining the minimum number of interval minimum values

When a number is modified, it will not be modified if the number is affected and deleted.

#include<bits/stdc++.h>
using namespace std;
const int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ob==ib)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ob==ib)?EOF:*ib++;
}
#define gc getchar
inline int read(){
    char ch=gc();
    int res=0,f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
#define ll long long
#define re register
#define pii pair<int,int>
#define fi first
#define se second
#define pb push_back
#define cs const
#define bg begin
inline void chemx(int &a,int b){a<b?a=b:0;}
inline void chemn(int &a,int b){a>b?a=b:0;}
cs int N=550005;
namespace Seg{
	int mn[N<<2],s[N<<2],tr[N<<2],tag[N<<2];
	#define lc (u<<1)
	#define rc ((u<<1)|1)
	#define mid ((l+r)>>1)
	inline void pushup(int u){
		if(mn[lc]==mn[rc])mn[u]=mn[lc],s[u]=s[lc]+s[rc];
		else if(mn[lc]>mn[rc])mn[u]=mn[rc],s[u]=s[rc];
		else mn[u]=mn[lc],s[u]=s[lc];
		tr[u]=tr[lc]+tr[rc];
	}
	inline void build(int u,int l,int r){
		if(l==r){mn[u]=0,s[u]=tr[u]=1;return;}
		build(lc,l,mid),build(rc,mid+1,r);
		pushup(u);
	}
	inline void pushnow(int u,int k){
		mn[u]+=k,tag[u]+=k;if(mn[u]==0)tr[u]=s[u];else tr[u]=0;
	}
	inline void pushdown(int u){
		if(!tag[u])return;
		pushnow(lc,tag[u]),pushnow(rc,tag[u]);
		tag[u]=0;
	}
	inline void change(int u,int l,int r,int p,int k){
		if(l==r){mn[u]+=k,s[u]=1,tr[u]=(mn[u]==0);return;}
		pushdown(u);
		if(p<=mid)change(lc,l,mid,p,k);
		else change(rc,mid+1,r,p,k);
		pushup(u);
	}
	inline void update(int u,int l,int r,int st,int des,int k){
		if(st<=l&&r<=des){
			pushnow(u,k);return;
		}
		pushdown(u);
		if(st<=mid)update(lc,l,mid,st,des,k);
		if(mid<des)update(rc,mid+1,r,st,des,k);
		pushup(u);
	}
	inline int query(int u,int l,int r,int st,int des){
		if(st<=l&&r<=des)return tr[u];
		int res=0;pushdown(u);
		if(st<=mid)res+=query(lc,l,mid,st,des);
		if(mid<des)res+=query(rc,mid+1,r,st,des);
		pushup(u);return res;
	}
}
int n,m,buc[N],a[N],st,lim;
inline void add(int v){
	buc[v]++;
	if(v<=st+n)Seg::change(1,1,lim,v-buc[v]+1,1);
}
inline void dec(int v){
	if(v<=st+n)Seg::change(1,1,lim,v-buc[v]+1,-1);
	buc[v]--;	
}
int main(){
	n=read(),m=read();
	st=m+2,lim=n+m+st;
	Seg::build(1,1,lim);
	for(int i=1;i<=n;i++){
		a[i]=read()+st,add(a[i]);
	}
	for(int i=1;i<=m;i++){
		int p=read(),x=read();
		if(p>0){
			dec(a[p]);
			a[p]=x+st;
			add(a[p]);
		}
		else{
			if(x==-1){
				st++;
				int pos=st+n;
				if(buc[pos])Seg::update(1,1,lim,pos-buc[pos]+1,pos,1);
			}
			else{
				int pos=st+n;
				if(buc[pos])Seg::update(1,1,lim,pos-buc[pos]+1,pos,-1);
				st--;
			}
		}
		cout<<Seg::query(1,1,lim,st+1,st+n)<<'\n';
	}
}

Topics: less