【省選模擬】20/05/17

AA

  • 考慮按掃描線的順序處理對一個詢問有貢獻的修改,用數據結構維護出現的時間以及 1,+1-1,+1,問題即從一個時間向前第一個爲 kk 的時間,那麼我們維護後綴 maxmax 即可二分,O(npoly(logn))O(npoly(\log n))
 #include<bits/stdc++.h>
#define cs const
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
namespace IO{
	cs int Rlen=1<<22|1;
	inline char gc(){ 
		static char buf[Rlen],*p1,*p2;
		(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
		return p1==p2?EOF:*p1++;
	} int read(){
		int x=0; char c=gc(); bool f=false;
		while(!isdigit(c)) f=c=='-', c=gc();
		while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
		return f?-x:x;
	}
} using namespace IO;
cs int N = 2e5 + 50;
cs int INF = 1e9 + 7;
typedef pair<int, int> pi;
int n, m, a[N], b[N];
vector<pi> qry[N];
struct dat{ int typ, op, c; };
vector<dat> mf[N]; int as[N];
namespace SGT{
	cs int N = ::N << 2;
	#define mid ((l+r)>>1)
	pi vl[N];
	pi operator + (cs pi &a, cs pi &b){
		return mp(a.fi+b.fi, max(b.se, a.se+b.fi));
	}
	void up(int x){ vl[x] = vl[x<<1] + vl[x<<1|1]; }
	void ins(int x, int l, int r, int p, int v){
		if(l==r) return vl[x]=mp(v,v), void();
		(p<=mid)?ins(x<<1,l,mid,p,v):ins(x<<1|1,mid+1,r,p,v); up(x);
	}
	pi qry(int x, int l, int r, int L, int R){
		if(L<=l&&r<=R) return vl[x];
		if(R<=mid) return qry(x<<1,l,mid,L,R);
		if(L>mid) return qry(x<<1|1,mid+1,r,L,R);
		return qry(x<<1,l,mid,L,R) + qry(x<<1|1,mid+1,r,L,R);
	}
	#undef mid
}
int work(int k, int t){
	int l=1, r=t; 
	if(SGT::qry(1,1,m,1,t).se<k) return -1; 
	while(l<r){
		int mid=(l+r+1)>>1;
		if(SGT::qry(1,1,m,mid,t).se>=k) l=mid;
		else r=mid-1;
	} return a[l];
}
int main(){
	#ifdef FSYolanda
	freopen("stack6.in","r",stdin);
//	freopen("tmp.out","w",stdout);
	#endif
	n=read(), m=read();
	static bool vs[N];
	for(int i=1,op,l,r; i<=m; i++){
		op=read(), l=read(), r=read();
		if(op==1) a[i]=read(); 
		if(op==3){
			qry[l].pb(mp(r,i)); 
			vs[i] = true; continue;
		} op = op==1 ? 1 : -1;
		mf[l].pb((dat){op,1,i});
		mf[r+1].pb((dat){op,-1,i});
	} 
	for(int i=1; i<=n; i++){
		for(int e=0; e<mf[i].size(); e++){
			dat x = mf[i][e];
			if(x.op == -1) SGT :: ins(1,1,m,x.c,0);
			else SGT :: ins(1,1,m,x.c,x.typ);
		} for(int e=0; e<qry[i].size(); e++){
			pi x = qry[i][e];
			as[x.se] = work(x.fi,x.se);
		}
	}
	for(int i=1; i<=m; i++) if(vs[i]){
		if(~as[i]) cout << as[i] << '\n';
		else puts("Error");
	} return 0;
}

BB

  • min25min25 即可,O(n3/4logn)O(\frac{n^{3/4}}{\log n})
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
typedef long long ll;
cs int N = 1e5 + 50;
int prm[N], pc; bool isp[N];
int T, n, S;
void linear_sieve(int n){
	pc=0; for(int i=2; i<=n; i++){
		if(!isp[i]) prm[++pc]=i;
		for(int j=1; j<=pc; j++){
			if(prm[j]*i>n) break;
			isp[prm[j]*i]=true; if(i%prm[j]==0) break;
		}
	} 
}
int A[N], B[N], vl[N], nd; ll f[N];
int idx(int x){ return x<=S?A[x]:B[n/x]; }
ll work(int x, int n){
	if(n<=1||n<prm[x]) return 0;
	ll as = f[idx(n)] - (x-1) * 3ll;
	for(int i=x; i<=pc; i++){
		if(prm[i]*prm[i]>n) break;
		for(int e=1,t=prm[i];(ll)t*prm[i]<=n;t*=prm[i],++e){
			as += work(i+1,n/t) * (2ll*e+1);
			as += 2ll*(e+1)+1;
		}
	} return as;
}
void Main(){
	scanf("%d",&n); linear_sieve(S=sqrt(n));
	nd=0; for(int l=1,r; l<=n; l=r+1){
		int v=n/l; r=n/v; 
		if(v<=S) A[v]=++nd;
		else B[n/v]=++nd; vl[nd]=v;
	} for(int i=1; i<=nd; i++) f[i]=3ll*(vl[i]-1);
	for(int i=1; i<=pc; i++)
	for(int j=1; j<=nd; j++){
		if(prm[i] * prm[i] > vl[j]) break;
		int t = idx(vl[j]/prm[i]);
		f[j] -= f[t]-3ll*(i-1);
	} cout << work(1,n)+1 << '\n';
}
int main(){
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
	scanf("%d",&T);
	while(T--) Main(); return 0;
} 

CC

  • 考慮最大化的時候有一個取到端點,這個可以通過旋轉卡殼得到
  • 最小化的時候考慮兩條對邊,若平行可以簡單計算答案,若不平行,將兩條線延長求交點,考慮夾角爲定值,面積爲定值,最小化底邊長度,那麼一定是等腰三角形,即 absinα=C,minimize(a2+b22abcosα)ab\sin \alpha=C,minimize(a^2+b^2-2abcos\alpha),同樣可以簡單計算答案,O(n)O(n)
#include<bits/stdc++.h>
#define cs const
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
namespace IO{
	cs int Rlen=1<<22|1;
	inline char gc(){ 
		static char buf[Rlen],*p1,*p2;
		(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
		return p1==p2?EOF:*p1++;
	} int read(){
		int x=0; char c=gc(); bool f=false;
		while(!isdigit(c)) f=c=='-', c=gc();
		while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
		return f?-x:x;
	}
} using namespace IO;
cs int N = 5e3 + 50;
double eps = 1e-10;
double INF = 1e18;
int sgn(double a){ return (a>eps)-(a<-eps); }
struct pnt{
	double x, y; pnt(double _x=0, double _y=0){ x=_x; y=_y; }
	void input(){ x=read(), y=read(); }
	void output(){ cout<<x<<" "<<y<<'\n'; }
	pnt operator + (cs pnt &a){ return pnt(x+a.x, y+a.y); }
	pnt operator - (cs pnt &a){ return pnt(x-a.x, y-a.y); }
	double operator * (cs pnt &a){ return x * a.y - y * a.x; }
	pnt operator * (cs double &a){ return pnt(x*a, y*a); }
	double len(){ return sqrt(x * x + y * y); }
	void norm(){ double t = len(); x = x / t; y = y / t; }
};
#define idx(x) (x>n?x-n:x)
int n; pnt a[N];
double S, A, B;
double dis(pnt a, pnt b){ return (b - a).len(); }
double calc(pnt a, pnt b, pnt c){
	double k = fabs((b-a) * (c-a));
	return k / dis(b,c);
}
pnt crs(pnt a, pnt b, pnt c, pnt d){
	double S1=(c-a)*(d-a), S2=(c-b)*(d-b);
	assert(sgn(S1-S2));
	return a + (b-a) * (S1/(S1-S2));
}
double ang(pnt a, pnt b){
	return asin(fabs(a*b)/(a.len()*b.len()));	
}
void work_mx(){
	double now = 0;
	for(int i=1,j=1; i<=n; i++){
		if(j<=i) j=i+1, now = a[i] * a[idx(i+1)];
		while(true){
			if(now + (a[idx(j)] * a[i]) > S) break;
			now += a[idx(j)] * a[idx(j+1)]; ++j; 
		} double nS = now + a[idx(j)] * a[i] - S;
		double d = calc(a[i],a[idx(j-1)],a[idx(j)]);
		double len = nS / d; pnt dir = a[idx(j-1)] - a[idx(j)];
		dir.norm(); dir = dir * len; pnt t = a[idx(j)] + dir;
		A = max(A, dis(a[i],t));
		B = min(B, dis(a[i],t)); now -= a[i] * a[i+1];
	}  
}
void work_mn(){
	double now = 0;
	for(int i=1,j=1; i<=n; i++){
		if(j<=i) j=i+1, now = a[i] * a[idx(i+1)];
		while(true){
			if(now + (a[idx(j)] * a[i]) > S) break;
			now += a[idx(j)] * a[idx(j+1)]; ++j; 
		} double nS = now + a[idx(j)] * a[i] - S;
		pnt dx = a[i] - a[i+1], dy = a[idx(j)] - a[idx(j-1)];
		if(!sgn(dx * dy)){
			double d = calc(a[i],a[idx(j-1)],a[idx(j)]);
			int len = min(dis(a[i],a[i+1]), dis(a[idx(j)],a[idx(j-1)]));
			if(nS <= d * len) B = min(B, d);
		} else{
			pnt v = crs(a[i+1],a[i],a[idx(j-1)],a[idx(j)]);
			int x = i, y = idx(j), tx = i+1, ty = idx(j-1); 
			if(sgn((a[i]-v) * (a[idx(j)]-v)) < 0) swap(x,tx), swap(y,ty), nS = S;
			nS = nS + fabs((a[x]-v) * (a[y]-v));
			double an = ang(a[x]-v, a[y]-v);
			double len = sqrt(nS/sin(an));
			double l1=(a[x]-v).len(), r1=l1+dis(a[x],a[tx]);
			double l2=(a[y]-v).len(), r2=l2+dis(a[y],a[ty]);
			if(max(l1,l2)<=len && len<=min(r1,r2)) 
			B = min(B, sqrt(2*nS/sin(an)*(1-cos(an))));
		} now -= a[i] * a[i+1];
	}
}
int main(){
	#ifdef FSYolanda
	freopen("1.in","r",stdin);
	#endif
	n=read(); 
	for(int i=1; i<=n; i++) a[i].input(); a[n+1] = a[1];
	for(int i=1; i<=n; i++) S += a[i] * a[i+1];
	S = S * 0.5; B = INF; work_mx(), work_mn();
	printf("%.8lf\n%.8lf",B,A); return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章