最终四题,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;
}
还有 Spy's Work这题 没被坑的话还有时间搞这题的
#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;
}