# 2014 UESTC暑前集训数据结构专题解题报告

A.Islands

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 1007

struct node
{
int x,y,h;
}p[N*N];

int a[N*N],sh[100005],cnt[100005],fa[N*N];
int n,m;
int dx[4] = {0,0,1,-1};
int dy[4] = {1,-1,0,0};

int cmp(node ka,node kb)
{
return ka.h < kb.h;
}

int findset(int x)
{
if(x != fa[x])
fa[x] = findset(fa[x]);
return fa[x];
}

inline int ok(int x,int y)
{
if(x < n && x >= 0 && y < m && y >= 0)
return 1;
return 0;
}

int main()
{
int t,i,j,k,q,ind,pos;
scanf("%d",&t);
while(t--)
{
memset(cnt,0,sizeof(cnt));
scanf("%d%d",&n,&m);
for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
{
pos = i*m+j;
fa[pos] = pos;
scanf("%d",&a[pos]);
p[pos].x = i,p[pos].y = j,p[pos].h = a[pos];
}
}
scanf("%d",&q);
for(i=0;i<q;i++)
scanf("%d",&sh[i]);
sort(p,p+n*m,cmp);
i = n*m-1;
for(j=q-1;j>=0;j--)
{
cnt[j] = cnt[j+1];
while(sh[j] < p[i].h)  //浮出水面
{
cnt[j]++;
ind = p[i].x*m+p[i].y;
int fx = findset(ind);
for(k=0;k<4;k++)
{
int tx = p[i].x + dx[k];
int ty = p[i].y + dy[k];
if(!ok(tx,ty))
continue;
int newind = tx*m+ty;
int fy = findset(newind);
if(fx != fy && sh[j] < a[newind]) //浮出水面且没有合并
{
fa[fy] = fx;   //不能使fa[fx] = fy.因为本次fx不会再findset.
cnt[j]--;
}
}
i--;
}
}
for(i=0;i<q;i++)
printf("%d ",cnt[i]);
printf("\n");
}
return 0;
}
View Code

B.母仪天下

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#define Mod 1000000007
#define INF 1000000007
#define INT 2147483647
#define lll __int64
#define ll long long
using namespace std;
#define N 100007

struct node
{
ll sum;
}tree[4*N];

void pushup(int rt)
{
tree[rt].sum = tree[2*rt].sum + tree[2*rt+1].sum;
}

void build(int l,int r,int rt)
{
if(l == r)
{
scanf("%lld",&tree[rt].sum);
return;
}
int mid = (l+r)/2;
build(l,mid,2*rt);
build(mid+1,r,2*rt+1);
pushup(rt);
}

void update(int l,int r,int pos,ll val,int rt)
{
if(l == r)
{
tree[rt].sum += val;
return;
}
int mid = (l+r)/2;
if(pos <= mid)
update(l,mid,pos,val,2*rt);
else
update(mid+1,r,pos,val,2*rt+1);
pushup(rt);
}

ll query(int l,int r,int aa,int bb,int rt)
{
if(aa <= l && bb >= r)
return tree[rt].sum;
int mid = (l+r)/2;
ll res = 0;
if(aa <= mid)
res += query(l,mid,aa,bb,2*rt);
if(bb > mid)
res += query(mid+1,r,aa,bb,2*rt+1);
return res;
}

int main()
{
int m,n,aa,bb;
int i,pos;
ll val;
while(scanf("%d%d",&n,&m)!=EOF)
{
build(1,n,1);
while(m--)
{
scanf("%d",&i);
if(i == 0)
{
scanf("%d%d",&aa,&bb);
printf("%lld\n",query(1,n,aa,bb,1));
}
else
{
scanf("%d%lld",&pos,&val);
update(1,n,pos,val,1);
}
}
}
return 0;
}
View Code

C.东风不与周郎便

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#define Mod 1000000007
#define INF 1000000007
#define INT 2147483647
#define lll __int64
#define ll long long
using namespace std;
#define N 100007

struct node
{
ll sum;
ll mark;
}tree[4*N];

void pushup(int rt)
{
tree[rt].sum = tree[2*rt].sum + tree[2*rt+1].sum;
}

void pushdown(int l,int r,int rt)
{
if(!tree[rt].mark)
return;
int mid = (l+r)/2;
tree[2*rt].sum += tree[rt].mark*(ll)(mid-l+1);
tree[2*rt+1].sum += tree[rt].mark*(ll)(r-mid);
tree[2*rt].mark += tree[rt].mark;
tree[2*rt+1].mark += tree[rt].mark;
tree[rt].mark = 0;
}

void build(int l,int r,int rt)
{
if(l == r)
{
scanf("%lld",&tree[rt].sum);
tree[rt].mark = 0;
return;
}
int mid = (l+r)/2;
build(l,mid,2*rt);
build(mid+1,r,2*rt+1);
pushup(rt);
}

void update(int l,int r,int aa,int bb,ll val,int rt)
{
if(aa <= l && bb >= r)
{
tree[rt].sum += val*(ll)(r-l+1);
tree[rt].mark += val;
return;
}
pushdown(l,r,rt);
int mid = (l+r)/2;
if(aa <= mid)
update(l,mid,aa,bb,val,2*rt);
if(bb > mid)
update(mid+1,r,aa,bb,val,2*rt+1);
pushup(rt);
}

ll query(int l,int r,int aa,int bb,int rt)
{
if(aa <= l && bb >= r)
return tree[rt].sum;
pushdown(l,r,rt);
int mid = (l+r)/2;
ll res = 0;
if(aa <= mid)
res += query(l,mid,aa,bb,2*rt);
if(bb > mid)
res += query(mid+1,r,aa,bb,2*rt+1);
return res;
}

int main()
{
int m,n,aa,bb;
int i;
ll val;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(tree,0,sizeof(tree));
build(1,n,1);
while(m--)
{
scanf("%d",&i);
if(i == 0)
{
scanf("%d%d",&aa,&bb);
printf("%lld\n",query(1,n,aa,bb,1));
}
else
{
scanf("%d%d%lld",&aa,&bb,&val);
update(1,n,aa,bb,val,1);
}
}
}
return 0;
}
View Code

D.长使英雄泪满襟

E.休生伤杜景死惊开

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#define Mod 1000000007
#define INF 1000000007
#define INT 2147483647
#define lll __int64
#define ll long long
using namespace std;
#define N 50007

struct node
{
ll sum;
}tree[4*N];

ll a[N],k1[N],k2[N];

void build(int l,int r,int rt)
{
tree[rt].sum = 0;
if(l == r)
return;
int mid = (l+r)/2;
build(l,mid,2*rt);
build(mid+1,r,2*rt+1);
}

ll query(int l,int r,int aa,int bb,int rt)
{
if(aa > bb)
return 0;
if(aa <= l && bb >= r)
return tree[rt].sum;
int mid = (l+r)/2;
ll res = 0;
if(aa <= mid)
res += query(l,mid,aa,bb,2*rt);
if(bb > mid)
res += query(mid+1,r,aa,bb,2*rt+1);
return res;
}

void update(int l,int r,int pos,int rt)
{
tree[rt].sum++;
if(l == r)
return;
int mid = (l+r)/2;
if(pos <= mid)
update(l,mid,pos,2*rt);
else
update(mid+1,r,pos,2*rt+1);
}

int main()
{
int n,i,j;
while(scanf("%d",&n)!=EOF)
{
ll sum = 0;
for(i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,n,1);
for(i=1;i<=n;i++)
{
k1[i] = query(1,n,1,a[i]-1,1);
update(1,n,a[i],1);
}
build(1,n,1);
for(i=n;i>=1;i--)
{
k2[i] = query(1,n,1,a[i]-1,1);
update(1,n,a[i],1);
}
for(i=1;i<=n;i++)
sum += k1[i] * k2[i];
printf("%lld\n",sum);
}
return 0;
}
View Code

F.天下归晋

（注意树状数组c[]数组下标只能从1开始，所以所有坐标在处理时都加1）

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 202010

struct point
{
int x,y;
}a[N];

int n;
int c[N],ans[N];

int cmp(point ka,point kb)
{
if(ka.y == kb.y)
return ka.x < kb.x;
return ka.y < kb.y;
}

int lowbit(int x)
{
return x&(-x);
}

void modify(int num,int val)
{
while(num<=N)
{
c[num] += val;
num += lowbit(num);
}
}

int sum(int x)
{
int res = 0;
while(x>0)
{
res += c[x];
x -= lowbit(x);
}
return res;
}

int main()
{
int i,x,y;
while(scanf("%d",&n)!=EOF)
{
memset(c,0,sizeof(c));
memset(ans,0,sizeof(ans));
for(i=0;i<n;i++)
scanf("%d%d",&a[i].x,&a[i].y);
sort(a,a+n,cmp);
for(i=0;i<n;i++)
{
ans[sum(a[i].x+1)]++;
modify(a[i].x+1,1);
}
for(i=0;i<n;i++)
{
printf("%d\n",ans[i]);
}
}
return 0;
}
View Code

G.程序设计竞赛

max:此区间内的最大连续和
sum:该节点以下的节点值得总和
lmax:此区间的从左端开始的最大连续和
rmax:此区间的从右端开始的最大连续和

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 200007

struct node
{
int maxi,lmaxi,rmaxi,sum;
}tree[4*N];

void pushup(int rt)
{
tree[rt].sum = tree[2*rt].sum + tree[2*rt+1].sum;
tree[rt].maxi = max(tree[2*rt].maxi,max(tree[2*rt+1].maxi,tree[2*rt].rmaxi+tree[2*rt+1].lmaxi));
tree[rt].lmaxi = max(tree[2*rt].lmaxi,tree[2*rt].sum + tree[2*rt+1].lmaxi);
tree[rt].rmaxi = max(tree[2*rt+1].rmaxi,tree[2*rt+1].sum + tree[2*rt].rmaxi);
}

void build(int l,int r,int rt)
{
if(l == r)
{
scanf("%d",&tree[rt].sum);
tree[rt].maxi = tree[rt].lmaxi = tree[rt].rmaxi = tree[rt].sum;
return;
}
int mid = (l+r)/2;
build(l,mid,2*rt);
build(mid+1,r,2*rt+1);
pushup(rt);
}

void update(int l,int r,int pos,int val,int rt)
{
if(l == r)
{
tree[rt].maxi = tree[rt].lmaxi = tree[rt].rmaxi = tree[rt].sum = val;
return;
}
int mid = (l+r)/2;
if(pos <= mid)
update(l,mid,pos,val,2*rt);
else
update(mid+1,r,pos,val,2*rt+1);
pushup(rt);
}

node query(int l,int r,int aa,int bb,int rt)
{
if(aa <= l && bb >= r)
return tree[rt];
int mid = (l+r)/2;
node ka,kb,res;
int flag1 = 0;
int flag2 = 0;
if(aa <= mid)
{
ka = query(l,mid,aa,bb,2*rt);
flag1 = 1;
}
if(bb > mid)
{
kb = query(mid+1,r,aa,bb,2*rt+1);
flag2 = 1;
}
if(flag1 && flag2)
{
res.sum = ka.sum + kb.sum;
res.lmaxi = max(ka.lmaxi,ka.sum+kb.lmaxi);
res.rmaxi = max(kb.rmaxi,kb.sum+ka.rmaxi);
res.maxi = max(ka.rmaxi+kb.lmaxi,max(ka.maxi,kb.maxi));
}
else
{
if(flag1)  //left
res = ka;
else
res = kb;
}
return res;
}

int main()
{
int n,m,op,aa,bb;
scanf("%d%d",&n,&m);
build(1,n,1);
while(m--)
{
scanf("%d%d%d",&op,&aa,&bb);
if(!op)
{
node res = query(1,n,aa,bb,1);
printf("%d\n",res.maxi);
}
else
update(1,n,aa,bb,1);
}
return 0;
}
View Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <cstdlib>
#include <string>
#include <vector>
#include <map>
#define Mod 1000000007
#define INF 1000000007
#define INT 2147483647
#define lll __int64
#define ll long long
using namespace std;
#define N 600007

struct node
{
int sum;
}tree[4*N];

struct A
{
int ind,val;
}a[N],b[N];

int hash[N],k[N];

int cmp(A ka,A kb)
{
return ka.val < kb.val;
}

void build(int l,int r,int rt)
{
tree[rt].sum = 0;
if(l == r)
return;
int mid = (l+r)/2;
build(l,mid,2*rt);
build(mid+1,r,2*rt+1);
}

int query(int l,int r,int pos,int rt)
{
tree[rt].sum--;
if(l == r)
return l;
int mid = (l+r)/2;
if(tree[2*rt].sum >= pos)
return query(l,mid,pos,2*rt);
else
return query(mid+1,r,pos-tree[2*rt].sum,2*rt+1);
}

void update(int l,int r,int pos,int rt)
{
tree[rt].sum++;
if(l == r)
return;
int mid = (l+r)/2;
if(pos <= mid)
update(l,mid,pos,2*rt);
else
update(mid+1,r,pos,2*rt+1);
}

int main()
{
int n,i,j,m;
char ss[14];
i = 1;
while(scanf("%s",ss)!=EOF)
{
if(ss[0] == '#')
a[i].val = b[i].val = INF,a[i].ind = b[i].ind = i++;
else
a[i].val = b[i].val = atoi(ss),a[i].ind = b[i].ind = i++;
}
m = i-1;
sort(b+1,b+m+1,cmp);
int now = 1;
int pre = -1000000000;
for(i=1;i<=m;i++)
{
if(b[i].val == INF)
continue;
if(b[i].val != pre)
{
pre = b[i].val;
b[i].val = now++;
}
else
b[i].val = now-1;
hash[b[i].val] = b[i].ind;
}
for(i=1;i<=m;i++)
k[b[i].ind] = b[i].val;
n = 600000;
build(1,n,1);
int cnt = 0;
for(i=1;i<=m;i++)
{
if(k[i] == INF)
{
if(cnt%2)  //odd
printf("%d\n",a[hash[query(1,n,(cnt+1)/2,1)]].val);
else
printf("%d\n",a[hash[query(1,n,cnt/2+1,1)]].val);
cnt--;
}
else
{
update(1,n,k[i],1);
cnt++;
}
}
return 0;
}
View Code

I.方师傅学数字逻辑

J.方师傅的01串

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 50007

struct node
{
int count,deep;
node *next[2];
}*root;

char ss[N];
int maxi;

node *create()
{
node *p;
p = (node *)malloc(sizeof(node));
p->count = 0;
p->deep = 0;
for(int i=0;i<2;i++)
p->next[i] = NULL;
return p;
}

void release(node *p)
{
for(int i=0;i<2;i++)
{
if(p->next[i] != NULL)
release(p->next[i]);
}
free(p);
}

void insert(char *ss)
{
node *p = root;
int i = 0,k;
while(ss[i])
{
k = ss[i++] - '0';
if(p->next[k] == NULL)
p->next[k] = create();
p->next[k]->deep = p->deep + 1;
p = p->next[k];
p->count++;
maxi = max(maxi,p->count*p->deep);
}
}

int main()
{
int t,n,i;
root = create();
scanf("%d",&n);
maxi = -1000000;
for(i=0;i<n;i++)
{
scanf("%s",ss);
insert(ss);
}
cout<<maxi<<endl;
release(root);
return 0;
}
View Code

K.方师傅与栈

1.终态的数还没模拟完，原始数组中的数就已经全部压入栈中了。并且栈顶还不等于终态此时需要的数
2.如果最后栈不为空，说明还有没有匹配的，自然不行。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define N 1000007

int a[N],want[N],stk[N];

int main()
{
int n,i,k,top;
scanf("%d",&n);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
scanf("%d",&want[i]);
k = 1;
top = 0;
stk[0] = 0;
int flag = 1;
for(i=1;i<=n;i++)
{
while(stk[top] != want[i])
{
if(k <= n)
stk[++top] = a[k++];
else
{
flag = 0;
break;
}
}
if(stk[top] == want[i])
top--;
if(!flag)
break;
}
if(!flag || top)
puts("No");
else
puts("Yes");
return 0;
}
View Code

L.冰雪奇缘

M.方师傅玩炉石

（没做出来的以后更新）

posted @ 2014-05-02 19:35 whatbeg 阅读(...) 评论(...) 编辑 收藏