NOIP2011TGsolution
Posted Melacau----论一个蒟蒻的自我修养
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2011TGsolution相关的知识,希望对你有一定的参考价值。
老师最近叫我把NOIPTG的题目给刷掉,于是就开始刷吧= =
链接:https://www.luogu.org/problem/lists?name=&orderitem=pid&tag=83%2C28
D1T1:carpet
题意简析:一个平面内有多个矩形按顺序覆盖平面,问覆盖后某个点属于哪个矩形。
解题思路:从n~1倒着check点有没有在矩形内即可,时间效率O(n)。
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #define For(i,a,b) for (int i=a; i<=b; i++) #define Ford(i,a,b) for (int i=a; i>=b; i--) #define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout); #define mem(qaq,num) memset(qaq,num,sizeof(qaq)); #define ll long long #define mod 1000000007 #define INF 2000000000 using namespace std; struct zxy{ int a,b,x,y; }rect[10001]; int n,x,y; inline int in(){ int x=0,f=1; char ch=getchar(); while (ch<‘0‘||ch>‘9‘) f=ch==‘-‘?-1:1,ch=getchar(); while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return x*f; } int main(){ n=in(); For(i,1,n) rect[i].a=in(),rect[i].b=in(),rect,rect[i].x=in()+rect[i].a,rect[i].y=in()+rect[i].b; x=in(),y=in(); Ford(i,n,1){ if (x>=rect[i].a&&x<=rect[i].x&&y>=rect[i].b&&y<=rect[i].y){ printf("%d",i); return 0; } } printf("-1"); }
D1T2:hotel
题意简析:给你n个客栈,叫你选取任意2个色调相同的不同客栈,且它们之间(包括本身)所有的客栈内存在最低消费不超过p的咖啡店,问你有多少种方案。
解题思路:这题貌似有O(n)的算法,但是我只想到O(n^2)的贪心,然后用线段树存区间最小值优化一个log,然后存下不同色调的客栈数,顺推一下就行了。时间效率O(nlog2n).
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #define For(i,a,b) for (int i=a; i<=b; i++) #define Ford(i,a,b) for (int i=a; i>=b; i--) #define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout); #define mem(qaq,num) memset(qaq,num,sizeof(qaq)); #define ll long long #define mod 1000000007 #define INF 2000000000 #define mid ((l+r)>>1) using namespace std; int mi[600000],color[50][200000],cnt[50],lst[50],n,k,p; inline int in(){ int x=0,f=1; char ch=getchar(); while (ch<‘0‘||ch>‘9‘) f=ch==‘-‘?-1:1,ch=getchar(); while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return x*f; } inline void update(int x,int k,int l,int r,int add){ if (l==r) { mi[k]=add; return; } if (x<=mid) update(x,k<<1,l,mid,add); else update(x,k<<1|1,mid+1,r,add); mi[k]=min(mi[k<<1],mi[k<<1|1]); } inline int query(int l,int r,int k,int a,int b){ if (!(l^a||r^b)) return mi[k]; if (b<=mid) return query(l,mid,k<<1,a,b); if (a>mid) return query(mid+1,r,k<<1|1,a,b); return min(query(l,mid,k<<1,a,mid),query(mid+1,r,k<<1|1,mid+1,b)); } int main(){ mem(mi,127/3); n=in(),k=in(),p=in(); For(i,1,n){ int cl=in(),x=in(); color[cl][++cnt[cl]]=i; update(i,1,1,n,x); } ll ans=0; For(i,0,k-1) For(j,2,cnt[i]){ if (query(1,n,1,color[i][j-1],color[i][j])<=p) ans+=j-1,lst[i]=j-1; else ans+=lst[i]; } printf("%lld",ans); }
D1T3:mayan(待更新)
D2T1:factor
题意简析:就是题目要求的啊。
解题思路:把ax和by看成整体,杨辉三角形求完全k次方式的各项系数,然后再用ax和by代进去就行了。
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #define For(i,a,b) for (int i=a; i<=b; i++) #define Ford(i,a,b) for (int i=a; i>=b; i--) #define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout); #define mem(qaq,num) memset(qaq,num,sizeof(qaq)); #define ll long long #define mod 10007 #define INF 2000000000 using namespace std; int tri[1002][1002],n,m,k,a,b; inline int in(){ int x=0,f=1; char ch=getchar(); while (ch<‘0‘||ch>‘9‘) f=ch==‘-‘?-1:1,ch=getchar(); while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); return x*f; } inline int ksm(int a,int k){ if (!k) return 1; if (!(k^1)) return a%mod; int ans=ksm(a,k/2)%mod; if (k&1) return ans*ans%mod*a%mod; return ans*ans%mod; } int main(){ a=in()%mod,b=in()%mod,k=in(),n=in(),m=in(); tri[1][1]=1; For(i,2,k+1) For(j,1,i) tri[i][j]=(tri[i-1][j-1]+tri[i-1][j])%mod; printf("%d",ksm(a,n)*ksm(b,m)%mod*tri[k+1][k-n+1]%mod); }
D2T2:qc
题意简析:叫你确定一个参数W按照公式计算后使得|S-∑y[i]|最小。
解题思路:显然对于W的递增,有∑y[i]单调递减,我们考虑二分W,然后进行check。这样的效率是O(nmlogS)的,我们可以发现我们可以通过每次2分后进行一个O(n)的预处理,计算≥W的个数与总和前缀,这样就可以优化效率。时间效率O((n+m)log2(max(W[i])))
#include<cstdio> #include<iostream> #include<cstring> #include<string> #include<algorithm> #include<cmath> #define For(i,a,b) for (int i=a; i<=b; i++) #define Ford(i,a,b) for (int i=a; i>=b; i--) #define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout); #define mem(qaq,num) memset(qaq,num,sizeof(qaq)); #define mod 1000000007 #define INF 1e18 #define mid (l+r>>1) using namespace std; int cnt[200001],sum[200001],w[200001],n,m,ll[200001],rr[200001],maw,miw=0x7fffffff,v[200001]; long long s,ans=1e18; template <class T> inline void in(T &x){ x=0; short f=1; char ch=getchar(); while (ch<‘0‘||ch>‘9‘) f=ch==‘-‘?-1:1,ch=getchar(); while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); x*=f; } void init(int k){ cnt[0]=sum[0]=0; For(i,1,n) if (w[i]>=k){ cnt[i]=cnt[i-1]+1; sum[i]=sum[i-1]+v[i]; } else cnt[i]=cnt[i-1],sum[i]=sum[i-1]; return; } inline void BS(int l,int r){ if (l>r) return; init(mid); long long tmp=0; For(i,1,m){ tmp+=abs((long long)((cnt[rr[i]]-cnt[ll[i]-1])*(sum[rr[i]]-sum[ll[i]-1]))); if (tmp>INF) break; } if (tmp==s){ ans=0; return; } if (tmp<s){ if (s-tmp<ans){ ans=s-tmp; } BS(l,mid-1); return; } if (tmp-s<ans){ ans=tmp-s; } BS(mid+1,r); } int main(){ in(n); in(m); in(s); For(i,1,n) in(w[i]),in(v[i]),miw=miw>w[i]?w[i]:miw,maw=maw<w[i]?w[i]:maw; For(i,1,m) in(ll[i]),in(rr[i]); BS(miw,maw); printf("%lld",ans); }
D2T3:bus
题意:就是一条链,每个点之间有限定条件,叫你求权值最小是多少。
解题思路:枚举每个加速器放在哪里,用前缀和优化找出对于可能的加速可以减少多少等待时间即可。时间效率O(kn)。(貌似有O(n)的算法)
#include<stdio.h> #define For(i,a,b) for (int i=a; i<=b; i++) #define Ford(i,a,b) for (int i=a; i>=b; i--) #define File(fn) freopen(fn".in","r",stdin); freopen(fn".out","w",stdout); #define ll long long #define mod 1000000007 #define INF 2000000000 int n,m,k,num[1001],st[1001],tim[1001],dis[1001],ans,use[1001]; struct zxy{ int a,b,t; }tou[10001]; template <class T> inline void in(T &x){ x=0; short f=1; char ch=getchar(); while (ch<‘0‘||ch>‘9‘) {if (ch==‘-‘) f=-1;ch=getchar();} while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar(); x*=f; } template <class T> inline void print(T x,char ch){ if (!x){ putchar(‘0‘); putchar(ch); return; } if (x<0){ putchar(‘-‘); x*=-1; } char num[20]; short cnt=0; while(x) num[++cnt]=x%10+‘0‘,x/=10; while(cnt) putchar(num[cnt--]); putchar(ch); }//for integer only template <class T> inline T max(T a,T b){ return a>b?a:b; } template <class T> inline T min(T a,T b){ return a<b?a:b; } template <class T> inline void abs(T &x){ x=x<0?-x:x; } void init(){ in(n),in(m),in(k); For(i,1,n-1) in(dis[i]); For(i,1,m) in(tou[i].t),in(tou[i].a),in(tou[i].b),num[tou[i].b]++,st[tou[i].a]=max(tou[i].t,st[tou[i].a]); For(i,2,n) num[i]+=num[i-1]; tim[1]=0; For(i,2,n) tim[i]=max(tim[i-1],st[i-1])+dis[i-1]; For(i,1,m) ans+=tim[tou[i].b]-tou[i].t; } void solve(){ while(k){ use[n]=use[n-1]=n; Ford(i,n-2,1) use[i]=tim[i+1]<=st[i+1]?i+1:use[i+1]; int np=0,p; For(i,1,n) if (num[use[i]]-num[i]>np&&dis[i]) np=num[use[i]]-num[i],p=i; if (!np) break; ans-=np; dis[p]--; k--; tim[1]=0; For(i,2,n) tim[i]=max(tim[i-1],st[i-1])+dis[i-1]; } print(ans,‘\n‘); } int main(){ init(); solve(); return 0; }
以上是关于NOIP2011TGsolution的主要内容,如果未能解决你的问题,请参考以下文章