前言
节日快乐!
(逃)
day10
50pts
期望:10+30+20=60
实际:0+30+20=50
rnk11
彻彻底底的摆烂局了。
但是rnk竟然没有太掉,所以我应该并不孤独…
和KH并排坐在机房里,各自看着电脑,痴痴想着各自的心事,一坐就是三个小时。
半小时三题了属于是
T1挂分是因为把题目描述的"连线"理解成了线段,但实际上是直线。
我不太确定还和KH统一了一下意见
个人感觉这个题意是真的很模糊,为什么不在比赛主页强调而要在钉钉啊!谁比赛的时候还会看钉钉啊qwq
事实是我那个靠着毁天灭地的剪枝竟然能过30,我也是惊了。
题目解析
圆与连线(circle)
挺妙的题目。
其实没有想像中那么难。
但完全没有往这边想过。
(而且题意都混淆不清)
考虑每个点落在圆上的两个切点,其对应两个旋转角组成一个区间。两个点可以同时存在的充要条件是其对应的区间相交且不包含。
然后就变成了线段问题,先按照左端点排序,然后暴力枚举第一条线段,把所有与它合法相交的线段提出来,拿右端点直接做一个最长上升子序列就行了。
(好久没写队列的最长上升子序列了,竟然莫名其妙的有些怀念)
转移石子(rock)
都叫它模拟费用流,但个人感觉这更像反悔贪心吧…
其实我考场上的大方向是对的,但是这个反悔没太整明白。
关键是给每配一对的权值加个-inf,这样就自然而然的保证必然会选满。
然后就是尝试在LCA处合并,并将反悔元素重新插入。
讨论一下几个深度的大小关系就可以得出,配对后两个反悔元素同时选取必然是不优的,所以不必担心同时取式子出bug的问题。(个人认为题解这个地方的讲解十分草率)
藏宝地图(treasure)
神仙扫描线dp。
完全没有往这方面想过…由于看到连通块一共只有 O(k)O(k)O(k) 个,所以一直以为是数据结构题,疯狂尝试建 k 棵树套树。
这个题最妙的地方应该就是对于障碍的处理了,通过奇技淫巧避免了十分麻烦的上下转移,确实十分巧妙。
一个细节问题是要注意障碍要先加后删。
代码
T1
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
void write(ll x){if(x>9) write(x/10);putchar('0'+x%10);
}
const int N=2e3+100;
const double pai=acos(-1.0);
const double eps=1e-10;int n,m;
int r;
int x[N],y[N];
struct line{double x,y;bool operator < (const line oth)const{return abs(x-oth.x)>eps?x<oth.x:y<oth.y;}
}l[N];
int ans;
double a[N],q[N];
int tot,num;
int f=0;
void calc(){num=0;for(int i=1;i<=tot;i++){if(!num||a[i]>q[num]-eps) q[++num]=a[i];else{int st=1,ed=num;while(st<ed){int mid=(st+ed)>>1;if(q[mid]>a[i]-eps) ed=mid;else st=mid+1;}q[st]=a[i];}//printf("i=%d num=%d\n",i,num);}ans=max(ans,num);if(f){for(int i=1;i<=tot;i++) printf("%lf ",a[i]);printf("\nnum=%d\n\n",num);}
}signed main(){//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);n=read();r=read();for(int i=1;i<=n;i++){x[i]=read();y[i]=read();double g=atan2(y[i],x[i]),d=acos(1.0*r/sqrt(x[i]*x[i]+y[i]*y[i]));l[i].x=g-d;l[i].y=g+d;if(l[i].x<-pai) l[i].x+=2*pai;if(l[i].y>pai) l[i].y-=2*pai;if(f) printf("(%lf %lf)\n",l[i].x/pai,l[i].y/pai);if(l[i].x>l[i].y) swap(l[i].x,l[i].y);} if(f) puts("");sort(l+1,l+1+n);if(f) for(int i=1;i<=n;i++) printf("(%lf %lf)\n",l[i].x,l[i].y);for(int now=1;now<=n;now++){a[tot=1]=l[now].y;for(int i=now+1;i<=n&&l[i].x<l[now].y+eps;i++){if(l[i].y>l[now].y-eps) a[++tot]=l[i].y;}calc();}printf("%d\n",ans);return 0;
}
/*
*/
T2
#include<bits/stdc++.h>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
void write(ll x){if(x>9) write(x/10);putchar('0'+x%10);
}
const int N=3e5+100;
const int M=2e6+100;
const double pai=acos(-1.0);
const ll inf=1e12;int n,m;
int dis[M],ls[M],rs[M];
ll val[M],tot,rub[M],num;
inline int New(ll v){int now=num?rub[num--]:++tot;val[now]=v;ls[now]=rs[now]=0;dis[now]=0;//printf(" New: now=%d v=%lld\n",now,v);return now;
}
int merge(int x,int y){if(!x||!y) return x|y;if(val[x]>val[y]) swap(x,y);rs[x]=merge(rs[x],y);if(dis[rs[x]]>dis[ls[x]]) swap(ls[x],rs[x]);dis[x]=dis[rs[x]]+1;return x;
}
inline ll top(int &x,int op=0){if(!x) return 1e18;ll res=val[x];if(op) rub[++num]=x,x=merge(ls[x],rs[x]);return res;
}
struct node{int to,nxt,w;
}p[N<<1];
int fi[N],cnt;
inline void addline(int x,int y,int w){p[++cnt]=(node){y,fi[x],w};fi[x]=cnt;
}
ll dep[N];
__gnu_pbds::priority_queue<ll,greater<ll>>a[N],b[N];
int xx[N],yy[N];
ll ans,S;
void dfs(int x,int f){for(int i=fi[x];~i;i=p[i].nxt){int to=p[i].to;if(to==f) continue;dep[to]=dep[x]+p[i].w;dfs(to,x);a[x].join(a[to]);b[x].join(b[to]);}//printf("\ndfs: x = %d\n",x);int o=min(xx[x],yy[x]);xx[x]-=o;yy[x]-=o;S-=o;if(xx[x]){for(int i=1;i<=xx[x];i++){//printf(" ins A: %lld\n",dep[x]);a[x].push(dep[x]);}}else if(yy[x]){//printf(" ins B: %lld\n",dep[x]-inf);for(int i=1;i<=yy[x];i++){b[x].push(dep[x]-inf);}}//printf(" a=%d topa=%lld b=%d topb=%lld\n",a[x],top(a[x]),b[x],top(b[x]));while(!a[x].empty()&&!b[x].empty()){ll u=a[x].top(),v=b[x].top();if(u+v-2*dep[x]>=0) break;ans+=u+v-2*dep[x];a[x].pop();b[x].pop();a[x].push(-v+2*dep[x]);b[x].push(-u+2*dep[x]);}return;
}signed main(){//freopen("rock.in","r",stdin);//freopen("rock.out","w",stdout);memset(fi,-1,sizeof(fi));cnt=-1;dis[0]=-1;n=read();for(int i=1;i<n;i++){int x=read(),y=read(),w=read();//printf("(%d %d %d)\n",x,y,w);addline(x,y,w);addline(y,x,w);}for(int i=1;i<=n;i++) xx[i]=read(),yy[i]=read(),S+=yy[i];dfs(1,0);printf("%lld\n",ans+S*inf);return 0;
}
/*
*/
T3
#include<bits/stdc++.h>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
#define ll long long
#define ull unsigned long long
#define debug(...) fprintf(stderr,__VA_ARGS__)
#define ok debug("OK\n")
inline ll read(){ll x(0),f(1);char c=getchar();while(!isdigit(c)){if(c=='-')f=-1;c=getchar();}while(isdigit(c)){x=(x<<1)+(x<<3)+c-'0';c=getchar();}return x*f;
}
void write(ll x){if(x>9) write(x/10);putchar('0'+x%10);
}
const int N=1e6;
const ll inf=1e12;int n,m;
int o=1e6;#define mid ((l+r)>>1)
#define ls (k<<1)
#define rs (k<<1|1)
int tr[N<<2],laz[N<<2];
inline void pushup(int k){tr[k]=tr[ls]+tr[rs];
}
inline void tag(int k){tr[k]=0;laz[k]=0;return;
}
inline void pushdown(int k){if(laz[k]!=-1){laz[k]=-1;tag(ls);tag(rs);}return;
}
int ask(int k,int l,int r,int x,int y){if(x>y) return 0;if(x<=l&&r<=y) return tr[k];pushdown(k);int res(0);if(x<=mid) res+=ask(ls,l,mid,x,y);if(y>mid) res+=ask(rs,mid+1,r,x,y);return res;
}
void add(int k,int l,int r,int p,int w){if(l==r){tr[k]+=w;return;}pushdown(k);if(p<=mid) add(ls,l,mid,p,w);else add(rs,mid+1,r,p,w);pushup(k);return;
}
void clear(int k,int l,int r,int x,int y){if(x<=l&&r<=y){tag(k);return;}pushdown(k);if(x<=mid) clear(ls,l,mid,x,y);if(y>mid) clear(rs,mid+1,r,x,y);pushup(k);
}//0:block
//1:treasure
//2:query
struct ope{int op,f;int x,y,id;int l,r;bool operator < (const ope oth)const{if(y!=oth.y) return y>oth.y;else if(op!=oth.op) return op<oth.op;else return f>oth.f;}
}q[N<<1];
int tot;
int val[N],ans[N];multiset<int>s;
multiset<int>::iterator it;signed main(){//freopen("treasure.in","r",stdin);//freopen("treasure.out","w",stdout); o+=2;memset(laz,-1,sizeof(laz));m=read();for(int i=1;i<=m;i++){int a=read(),b=read(),c=read(),d=read();++a;++b;++c;++d;q[++tot]=(ope){0,1,0,d,i,a,c};q[++tot]=(ope){0,-1,0,b-1,i,a,c};}m=read();for(int i=1;i<=m;i++){int x=read(),y=read();++x;++y;q[++tot]=(ope){1,0,x,y,0,0,0};}n=read();for(int i=1;i<=n;i++){int x=read(),y=read();++x;++y;q[++tot]=(ope){2,0,x,y,i,0,0};}sort(q+1,q+1+tot);s.insert(o);for(int i=1;i<=tot;i++){if(q[i].op==0){int l=q[i].l,r=q[i].r,id=q[i].id,ed=(*s.lower_bound(q[i].l));if(q[i].f==1){s.insert(l-1);s.insert(r);int res=ask(1,1,o,l,ed);val[id]=ask(1,1,o,r+1,ed);clear(1,1,o,l,r);add(1,1,o,l-1,res);}else{s.erase(s.find(l-1));s.erase(s.find(r));add(1,1,o,l-1,-val[id]);clear(1,1,o,l,r);}}else if(q[i].op==1) add(1,1,o,q[i].x,1);else{int pos=q[i].x;int ed=(*s.lower_bound(pos));ans[q[i].id]=ask(1,1,o,pos,ed);}}for(int i=1;i<=n;i++) printf("%d\n",ans[i]);return 0;
}
/*1 3*/
总结
昨天:“现在大部分题目基本上考场上都能想到正确的方向了”
今天就直接两道题完全抓瞎…
《天 高 地 厚》
就这考试也有人AK是我没想到的。
收下我的膝盖!
明天加油吧!awa