最终四题,100多名,没什么好说的,水水的。。。。
就是1006被坑的有点夸张,导致没有时间去搞其他题,不过好像很多队也被这题的题意坑了
比赛开始时我就瞄准了A题,肯定是线段树,但是怎么搞呢,线段树要开的空间好大啊,正犹豫中,队友树状数组1A - -
然后我看1002,问你Alice最多有多少的卡片可以覆盖Bob的卡片,每场卡片是a*b规格的,a b不可互换,开始想到的是先将Bob的所有卡片收集起来,放进线段树中,a这一维当做区间域,b当做值,然后将Alice的卡片排好序,一个个计算过去,找一张a值比它小的b值最大的卡片覆盖掉,但是立刻发现,这个操作无法完成,因为b值不具备单调性,于是瞬间想到只在b值上做文章,用平衡树维护b的单调性(线段树也可以,只不过我懒得离散化),具体做法是,对两个人的卡片分别排序,枚举Alice的卡片x,将bob的卡片中a值小于等于x.a的元素都依次加进平衡树(插入的是卡片的b值),然后就询问一下有没有小于等于x.b的节点存在,存在的话ans++,删除小于等于x.b的最大的b值,即平衡树中x.b的前驱节点
最后一题搜索在1002A了之后经过几次Wa也顺利AC了,刚好排50 - -!,形势一片大好。
然后就有了1006的出现,题意都错了还坚持说对的(然后人民群众肯定是相信admin的话喽),怪不得有人爆粗口。
然后各种造数据,各种对,就是找不出错。。。。
然后在被坑了许久之后怒A!!!!
然后就没有然后了。。。。。。。
其实还有两道题都挺简单的,跟树有关,想法都有了,一道是树DP+分组背包,另一道模拟一遍就好
献上B题代码
#include<cstdio> #include<set> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; const int maxn = 100010; #define L ch[rt][0] #define R ch[rt][1] int ch[maxn][2], aux[maxn] , num[maxn] , size[maxn] , cnt[maxn]; int val[maxn]; int tot,rt; inline void init(){ size[0]=0; rt = tot = 0;val[0]=-1; ch[0][0] = ch[0][1] = 0; aux[0] = 0; } inline void pushup(int rt){ size[rt]=cnt[rt]+size[L]+size[R]; } inline void Rotate(int &rt,int f){//f=1:右旋 f=0:左旋 int t = ch[rt][!f]; ch[rt][!f] = ch[t][f]; ch[t][f] = rt; pushup(rt);pushup(t); rt = t; } void insert(int &rt,int key){ if(!rt) { rt = ++tot; val[rt] = key; L = R = 0; size[rt]=cnt[rt]=1; aux[rt] = ( rand() << 14 ) + rand(); return ; } if(key==val[rt]) { ++cnt[rt]; }else if(key < val[rt]){ insert(L , key); if( aux[L] < aux[rt] ) Rotate(rt,1); }else { insert(R , key); if( aux[R] < aux[rt] ) Rotate(rt,0); } pushup(rt); } void treap_delete(int &rt){//real deletion if(!L || !R){ rt=L?L:R; }else { if(aux[L] < aux[R]){ Rotate(rt,1); treap_delete(R); }else { Rotate(rt,0); treap_delete(L); } } } void del(int &rt , int key){//lazy deletion if(key == val[rt]) { cnt[rt]--; size[rt]--; if(cnt[rt]==0) treap_delete(rt); } else { if(key < val[rt]) del(L,key); else del(R,key); size[rt]--; } } int find(int rt,int key){ if(!rt) return 0; else if(key < val[rt]) return find(L,key); else if(key > val[rt]) return find(R,key); else return cnt[rt]; } //找后继结点 void succ(int rt,int key,int &ans){//找>=key的第一个结点,即后继结点 if(!rt) return ; if(val[rt] >= key){ ans=val[rt]; succ(L,key,ans); }else succ(R,key,ans); } //找前驱结点 void pre(int rt,int key,int &ans){ if(!rt) return ; if(val[rt]<=key) { ans=val[rt]; pre(R,key,ans); }else pre(L,key,ans); } int getmin(int rt){ while(L) rt=L; return val[rt]; } int getmax(int rt){ while(R) rt=R; return val[rt]; } //找第k小的数 int find_kth(int rt,int k){ if(k<size[L]+1) return find_kth(L,k); else if(k>size[L]+cnt[rt]) return find_kth(R,k-size[L]-cnt[rt]); else return val[rt]; } //确定key的排名 int treap_rank(int rt,int key,int cur){//cur:当前已知比要求元素(key)小的数的个数 if(key == val[rt]) return size[L] + cur + 1; else if(key < val[rt]) treap_rank(L,key,cur); else treap_rank(R,key,cur+size[L]+cnt[rt]); } int get_lt(int rt,int key){//小于key的数的个数 lt:less than if(!rt) return 0; if(val[rt]>=key) return get_lt(L,key); return cnt[rt]+size[L]+get_lt(R,key); } int get_mt(int rt,int key){//大于key的数的个数 mt:more than if(!rt) return 0; if(val[rt]<=key) return get_mt(R,key) ; return cnt[rt]+size[R]+get_mt(L,key); } struct node{ int a,b; bool operator < (const node cmp)const{ return a<cmp.a; } }A[maxn],B[maxn]; int main() { int t,n; scanf("%d",&t); while(t--) { init(); scanf("%d",&n); for(int i=0;i<n;i++) { scanf("%d%d",&A[i].a,&A[i].b); } for(int i=0;i<n;i++) { scanf("%d%d",&B[i].a,&B[i].b); } sort(A,A+n); sort(B,B+n); int pa=0; int ans=0; for(int i=0;i<n;i++) { //printf("i=%d\n",i); while(pa<n && B[pa].a<=A[i].a) { //printf("hhe=%d\n",B[pa].b); insert(rt,B[pa].b); pa++; } int mi=getmin(rt); if(mi==-1) { continue; } if(mi <= A[i].b) { ans++; int pp; pre(rt,A[i].b,pp); del(rt,pp); } } printf("%d\n",ans); } return 0; }
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const __int64 inf = 1000000000; const int maxn = 10010; vector<int> edge[maxn]; bool ans; __int64 L[maxn],R[maxn]; struct node{ char op[5]; int w; }hehe[maxn]; vector<node> dd[maxn]; bool dfs(int u) { int sz=edge[u].size(); for(int i=0;i<sz;i++) { int v=edge[u][i]; if(!dfs(v)) return false; } L[u]=1;R[u]=inf; for(int i=0;i<sz;i++) { int v=edge[u][i]; L[u]+=L[v]; R[u]+=R[v]; } int size=dd[u].size(); for(int i=0;i<size;i++) { if(dd[u][i].op[0]=='>') { if(L[u] < dd[u][i].w+1) L[u]=dd[u][i].w+1; if(L[u]>R[u]) return false; } else if(dd[u][i].op[0]=='<') { if(R[u]>dd[u][i].w-1) R[u]=dd[u][i].w-1; if(L[u]>R[u]) return false; } else { if(L[u]>dd[u][i].w || R[u]<dd[u][i].w) return false; L[u]=R[u]=dd[u][i].w; } } return true; } int main() { int n,m; while(scanf("%d",&n)!=EOF) { int fa; for(int i=1;i<=n;i++) edge[i].clear(),dd[i].clear(); for(int i=2;i<=n;i++) { scanf("%d",&fa); edge[fa].push_back(i); } scanf("%d",&m); int u,w; char op[5]; for(int i=1;i<=m;i++) { node tmp; scanf("%d",&u); scanf("%s%d",tmp.op,&tmp.w); dd[u].push_back(tmp); } ans=dfs(1); if(ans) printf("True\n"); else printf("Lie\n"); } return 0; }