1、tju 3243 Blocked Road
http://acm.tju.edu.cn/toj/showp3243.html
道路形成了一个圆,从一点到令一点,有两条路线可以选择,走弧度较小的和弧度较大的。判断是否连通,我们可以先用j = Getsum(b-1) – Getsum(a – 1),如果j等于(b – a)或者Getsum(n) – j等于(n – (b – a)),那么点a, b联通。代码不见了。
2、SPOJ 227 Ordering the Soldiers
http://www.spoj.pl/problems/ORDERS/
首先明确树状数组是可以求第k大数的。由于getsum()是递增的,可以用二分求出使得getsum(j)==k的最小的j这道题和正常的树状数组题目相反,给出某点前面比他大的数的个数吗,求出此点。从后往前求,因为从后往前就能确定当前点是第几大的数,假设排在当前点前面比他大的数有一个·,点的个数为5,那么当前点必然为4.我们用树状数组来求第k大数。注意,由于我们可能先前已经删除了一些数,所以我们要找到最小的数使得他成为第k大数。
#include <stdio.h>
#include <string.h>
const int MAX = 200000 + 10;
int n;
int c[MAX], a[MAX], ans[MAX];
int lowbit(int x)
{
return x&(-x);
}
void update(int x, int v)
{
while (x<=n)
{
c[x] += v;
x += lowbit(x);
}
}
int getsum(int x)
{
int sum = 0;
while (x)
{
sum+=c[x];
x -= lowbit(x);
}
return sum;
}
int find(int v)
{
int l = 1, r = n, mid, t;
while (l < r)
{
mid = (l + r) >> 1;
t = getsum(mid);
if (t < v)
{
l = mid + 1;
}
else if (t >= v)
{
r = mid;
}
}
return r;
}
int main()
{
int t, i;
while (scanf("%d", &t)==1)
while (t--)
{
memset(c, 0, sizeof(c));
scanf("%d", &n);
for (i=1; i<=n; i++)
{
scanf("%d", a+i);
update(i, 1);
}
for (i=n; i>=1; i--)
{
ans[i] = find(i-a[i]);
update(ans[i], -1);
}
printf("%d", ans[1]);
for (i=2; i<=n; i++)
{
printf(" %d", ans[i]);
}
puts("");
}
return 0;
}
3、hdu 2852 KiKi's K-Number
http://acm.hdu.edu.cn/showproblem.php?pid=2852
裸的求第k大数;
#include <stdio.h>
#include <string.h>
const int MAX = 100000 + 10;
int m, p, e, a, k;
int c[MAX];
int lowbit(int x)
{
return x&(-x);
}
void update(int x, int v)
{
while (x<MAX)
{
c[x] += v;
x += lowbit(x);
}
}
int getsum(int x)
{
int sum = 0;
while (x)
{
sum+=c[x];
x -= lowbit(x);
}
return sum;
}
int main()
{
while (scanf("%d", &m)== 1)
{
memset(c, 0, sizeof(c));
while (m--)
{
scanf("%d", &p);
if (p == 0)
{
scanf("%d",&e);
update(e, 1);
}
if (p == 1)
{
scanf("%d",&e);
if (getsum(e) - getsum(e-1) == 0)
{
printf("No Elment!\n");
}
else
{
update(e, -1);
}
}
if (p == 2)
{
scanf("%d%d", &a, &k);
int t = getsum(a) +k;
int l = 1, r=MAX-1, mid;
while (l<r)
{
mid = (l + r) >> 1;
if (getsum(mid) <t)
{
l = mid+1;
}
else
{
r = mid;
}
}
if (l == MAX-1)
{
printf("Not Find!\n");
}
else
{
printf("%d\n", l);
}
}
}
}
return 0;
}