2017.05.21练习赛赛后总结
来源:互联网 发布:水资源优化配置 编辑:程序博客网 时间:2024/06/03 15:28
A
- 直接把块削平,排序找中位数即可
#include<bits/stdc++.h>using namespace std;typedef long long ll;const int M=300005;ll A[M*2],n,mi;ll s[M*2],sum;int main(){ mi=1e12*M; scanf("%d",&n); int mid=n/2+1; for(int i=1;i<=n;i++){ cin>>A[i]; A[i]-=abs(mid-i); } for(int i=1;i<=n;i++){ cin>>A[i+n]; A[i+n]-=abs(mid-i); } n*=2;sort(A+1,A+1+n); for(int i=1;i<=n;i++) s[i]=s[i-1]+A[i]; sum=s[n]; for(int i=1;i<=n;i++){ ll a=0,b=0; if(i>1)a=A[i]*(i-1)-s[i-1]; if(i<n)b=sum-s[i]-(n-i)*A[i]; mi=min(mi,a+b); } cout<<mi;}`
B
思考和分析
- 我们容易发现对于一个圆,如果它被刚好塞满了权值就为2,否则为1
这样我们有一个很清晰的目标了即判断每个圈是否被填满 - 我们可以很容易想到利用线段树来合并和收集信息,对于一个大圆我们先向树种放入他的子圆,之后查询它是否被填满即可
#include<bits/stdc++.h>using namespace std;#define M 300005struct node{ int x,r; bool operator <(const node &A)const{ return r<A.r; }}s[M];int P[M<<1];int tree[M<<3],m;map<int,int>mp;void up(int p){ tree[p]=tree[p<<1]&tree[p<<1|1];}void down(int p){ tree[p<<1]|=tree[p]; tree[p<<1|1]|=tree[p];}void update(int L,int R,int p=1,int l=1,int r=m){ if(L==l&&R==r){ tree[p]=1; return; } int mid=l+r>>1; if(R<=mid)update(L,R,p<<1,l,mid); else if(L>mid)update(L,R,p<<1|1,mid+1,r); else { update(L,mid,p<<1,l,mid); update(mid+1,R,p<<1|1,mid+1,r); } up(p);}bool query(int L,int R,int p=1,int l=1,int r=m){ down(p); if(L==l&&R==r)return tree[p]; int mid=l+r>>1; if(R<=mid)return query(L,R,p<<1,l,mid); if(L>mid)return query(L,R,p<<1|1,mid+1,r); return query(L,mid,p<<1,l,mid)&query(mid+1,R,p<<1|1,mid+1,r);}int main(){ int n,k=0; scanf("%d",&n); int ans=n+1; for(int i=1;i<=n;i++){ scanf("%d %d",&s[i].x,&s[i].r); P[++k]=s[i].x-s[i].r; P[++k]=s[i].x+s[i].r; } sort(P+1,P+k+1); m=unique(P+1,P+k+1)-P-1; for(int i=1;i<=m;i++)mp[P[i]]=i; sort(s+1,s+n+1); for(int i=1;i<=n;i++){ bool cnt=query(mp[s[i].x-s[i].r]+1,mp[s[i].x+s[i].r]); if(cnt)ans++; update(mp[s[i].x-s[i].r]+1,mp[s[i].x+s[i].r]); } printf("%d\n",ans); return 0; //by Once666Ac}
- 同时我们还有一个更简单的方法
#include<bits/stdc++.h>using namespace std;int n,stk[300005],t,ans;struct node{ int l,r; bool operator<(const node &A)const{ if(l!=A.l)return l<A.l; return r>A.r; }}A[300005];int main(){ scanf("%d",&n); for(int i=1,a,b;i<=n;i++){ scanf("%d%d",&a,&b); A[i]=(node){a-b,a+b}; } sort(A+1,A+1+n);//我们先以l在以r来排序一定保证先遍历大圆后遍历其中的小圆 for(int i=1;i<=n;i++){ while(t&&A[stk[t]].r<A[i].r)t--;//利用一个栈来保存大的圆,我们找到该圆外一层的圆 if(A[i].l==A[stk[t]].l)A[stk[t]].l=A[i].r;//如果相切直接把大圆的值改掉 stk[++t]=i; } for(int i=1;i<=n;i++)ans+=A[i].l==A[i].r;//大圆被填满了 printf("%d",ans+n+1); return 0;}
- 同时我还有一种神奇的方法
#include<bits/stdc++.h>using namespace std;const int M=3e5+5;priority_queue<int>L[2*M];struct node{int l,r;}G[M];int B[2*M],n,m,ans;void dfs(int l,int r){//找是否可以匹配一个l,r if(!L[l].empty()){ int R=L[l].top(); L[l].pop();//脱皮 dfs(l,R); if(R==r)ans++; else dfs(R,r); }}int main(){ scanf("%d",&n); ans=n+1; for(int i=1,a,b;i<=n;i++){ scanf("%d %d",&a,&b); int l=a-b,r=a+b; B[++m]=l;B[++m]=r; G[i]=(node){l,r}; } sort(B+1,B+1+m); int k=unique(B+1,B+1+m)-B-1; for(int i=1;i<=n;i++){ G[i].l=lower_bound(B+1,B+1+k,G[i].l)-B; G[i].r=lower_bound(B+1,B+1+k,G[i].r)-B; L[G[i].l].push(G[i].r); } for(int i=1;i<=n;i++){ if(!L[i].empty()){ int r=L[i].top(); L[i].pop();//脱皮 dfs(i,r); } } printf("%d",ans); }
C
分析和思考
- 我们可以分步来解决
/* 同正常的hash一样我们可以把它分解成两个串 我们在%P的情况下 k=(a*33*...33)^b k^b=a*B*B..*B; k^b*inv(B)...inv(B)=a 我们可以先预处理出前n/2项值为S的串cnt[S]*/ #include<bits/stdc++.h>using namespace std;typedef long long ll;int n,k,p,P,e,cnt[(1<<25)+5];ll ans,inv=1,b=33;void pre(int S,int k){ if(k)for(int i=1;i<=26;++i)pre(((1ll*S*33)^i)&P,k-1); else ++cnt[S];}void dp(int S,int k){ if(k)for(int i=1;i<=26;++i)dp((1ll*(S^i)*inv)&P,k-1); else ans+=cnt[S];}int main(){ scanf("%d%d%d",&n,&k,&p); P=1<<p,e=P-1; while(e){ if(e&1)inv=inv*b%P; b=b*b%P,e>>=1; }--P; pre(0,n/2);//先预处理出前一半 dp(k,n-n/2);//再计算出后一半 cout<<ans;}
小结
- 有类似这样性质的问题我们可以通过分布来解决
- 每个状态的转移没有顺序关系,没有后效性
- 保证每一步和每一步是完全独立的,即可以得到这样的S=A+B而A与B的值间没有任何影响
总
一些细节和思路上失误
- B
- 离散之后变量名打错了
- 没有想到利用线段树维护信息
- 没有深入挖掘题目的信息,没有想到可以通过排序得到圆的关系而在奇思妙想通过一些玄学的东西来解题
- 比赛的其他过程
- 在B题90分后,自暴自弃没有好好Debug
- 之后就一直抱着水分的心态乱写,浪费了许多时间
- 受到他人的影响太大,太在意没有用的东西(排名)
- 在B90分后做题的策略出现严重问题:不知道继续写还是Debug
阅读全文
1 0
- 2017.05.21练习赛赛后总结
- 2017.05.14练习赛赛后总结
- 练习赛20160319赛后总结
- 交流赛(赛后总结)
- ACM省赛赛后总结
- 理工校赛决赛赛后总结
- 赛后总结(怀化交流赛)
- 2014年湖南省赛赛后总结
- 2014ACM鞍山区域赛赛后总结
- 2015年浙江省省赛赛后总结
- 2017.3.11 NOIP训练赛赛后总结
- 2017.3.18 NOIP训练赛赛后总结
- 2017.3.18 NOIP训练赛赛后总结
- 2017CCCC天梯赛决赛 赛后总结
- 2017江苏省赛jscpc赛后总结
- NOIP2014 DAY1 模拟赛赛后总结
- NOIP2014 Day2 模拟赛赛后总结&题解
- 区域赛 赛后总结和个人计划
- Oracle11g 手动建库
- WCF不能传输超过10万条数据
- android 开机自动启动程序
- Linux中硬链接与软链接的区别与联系
- 面向对象编程的基本原则
- 2017.05.21练习赛赛后总结
- 一天一条shell命令--------退出状态
- 数据结构之双向链表
- Spring 多个配置文件
- Markdown语法参考
- 关于Java解压文件的一些坑及经验分享(MALFORMED异常)
- 基于信号处理的在线云评测+社区系统( 3)
- POJ3280-Cheapest Palindrome
- Android之仿IOS悬浮窗