1. HDU-1166 敌兵布阵

解题思路:版模题

#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 50000 << 2;
int num[maxn], S[maxn], L[maxn], R[maxn];

void build(int u, int l ,int r) {

	if(l == r) {
		S[u] = num[l];
		L[u] = R[u] = l;
		return ;
	}

	int mid = (l + r) / 2;
	build(2*u,l,mid);
	build(2*u+1,mid+1,r);
	S[u] = S[2*u] + S[2*u+1];
	L[u] = l;
	R[u] = r;
}

void add(int i,int j, int r) {

	if(R[r] == i && L[r] == i) {
		S[r] += j;
		return ;	
	}

	int mid = (L[r] + R[r]) / 2;
	if(i <= mid) 
		add(i,j,2*r);
	else
		add(i,j,2*r+1);
	S[r] += j;
}

void Sub(int i,int j, int r) {

	if(R[r] == i && L[r] == i) {
		S[r] -= j;
		return ;	
	}

	int mid = (L[r] + R[r]) / 2;
	if(i <= mid)
		Sub(i,j,2*r);
	else
		Sub(i,j,2*r+1);
	S[r] -= j;
}

int Query(int i, int j, int r) {

	if( i <= L[r] && R[r] <= j) 
		return S[r];	

	int mid = (L[r] + R[r]) / 2;
	int ans = 0;
	if (i <= mid)
		 ans += Query(i,j,2*r);
	if (j > mid)	
		ans += Query(i,j,2*r+1);
	return ans;
}

int main() {
	int test, N, mark = 1;
	char temp[100];
	scanf("%d",&test);

	while(test--) {	
		scanf("%d",&N);
		for(int i = 1; i <= N; i++)
			scanf("%d",&num[i]);
		build(1,1,N);
		int i,j;
		getchar();
		printf("Case %d:\n",mark++);
		while(1) {
			scanf("%s",temp);
			if (temp[0] == 'E')
				break;
			scanf("%d%d", &i, &j);
			getchar();
			if(strcmp("Add",temp) == 0)
				add(i,j,1);
			else if(strcmp("Sub",temp) == 0)
				Sub(i,j,1);
			else if(strcmp("Query",temp) == 0) 
				printf("%d\n",Query(i,j,1));
		}
	}
	return 0;
}

2.HDU 1754 I Hate it

解题思路:模板题

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 200000 << 2;
int S[maxn], L[maxn], R[maxn];
int num[maxn];
void build(int u, int l, int r) {

	if( l == r) {
		S[u] = num[l]; 	
		L[u] = l;
		R[u] = l;
		return ;
	}
	int mid = (l + r) / 2;
	build(2*u,l,mid);
	build(2*u+1,mid+1,r);
	S[u] = max(S[2*u],S[2*u+1]);
	L[u] = l;
	R[u] = r;
}

void modify(int id, int x, int u) {
	if(L[x] == id && R[x] == id)  {
		S[x] = u;
		return ;
	}

	int mid = (L[x] + R[x]) / 2;
	if(id <= mid)  
		modify(id,2*x,u); 
	else
		modify(id,2*x+1,u);

	S[x] = max(S[2*x],S[2*x+1]);
}

int search(int s, int e, int u) {

	if(L[u] >= s && R[u] <= e) 
		return S[u];	

	int mid = (L[u] + R[u]) / 2;

	if(s >= mid + 1)  
		return search(s,e,2*u+1);
	else if(e <= mid) 
		return search(s,e,2*u);
	else
		return max(search(s,e,2*u),search(s,e,2*u+1));
}

int main() {
	int N, M;
	int test;
	while(scanf("%d%d",&N,&M) == 2) {
		for(int i = 1; i <= N; i++)
			scanf("%d",&num[i]);
		build(1,1,N);
		getchar();
		int s, e;
		char c;
		for(int i = 0; i < M; i++) {
			scanf("%c%d%d",&c,&s,&e);	
			getchar();
			if(c == 'Q')
				printf("%d\n",search(s,e,1));
			else
				modify(s,1,e);
		}

	}
	return 0;
}


3.

UVA - 12299   RMQ with Shifts

解题思路:shift移动的话,就把相应节点的值改变一下,再把原数组改变一下就可以了

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 100010 << 2;
int num[maxn >> 2], S[maxn], R[maxn], L[maxn];
void build(int u, int l ,int r) {

	L[u] = l;
	R[u] = r;
	if(l == r) {
		S[u] = num[l];
		return;	
	}
	int mid = (l + r) / 2;
	build(2 * u, l , mid);
	build(2 * u + 1, mid + 1, r);
	S[u] = min(S[2 * u], S[2 * u + 1]);
}

int query(int l, int r, int u) {
	if(l <= L[u] && R[u] <= r)
		return S[u];
	int mid = (L[u] + R[u]) / 2;

	if(r <= mid)
		return query(l, r, 2 * u);
	else if(l > mid)
		return query(l, r, 2 * u + 1);
	else
		return min(query(l , r, 2 * u) , query(l, r, 2 * u + 1));
}

void shift(int x, int v, int u) {

	if(x == L[u] && R[u] == x) {
		S[u] = v;
		return ;	
	}

	int mid = (L[u] + R[u]) / 2;
	if(x <= mid) 
		shift(x, v, 2 * u);
	else
		shift(x, v, 2 * u + 1);

	S[u] = min(S[2 * u], S[2 * u + 1]);
}

int main() {
	int N, Q;
	scanf("%d%d", &N, &Q);

	for(int i = 1; i <= N; i++)
		scanf("%d",&num[i]);

	build(1,1,N);
	char str[300];
	while(Q--) {
		scanf("%s",str);
		if(str[0] == 'q') {
			int s, e;
			sscanf(str,"query(%d,%d)",&s,&e);
			printf("%d\n",query(s,e,1));
		}
		else {
			int t[30] = {0};
			int cnt = 0;

			for(int i = 6; str[i] != ')'; i++) {
				if(str[i] == ',') {
					cnt++;
					continue;
				}
				t[cnt] = ( t[cnt] * 10 ) + str[i] - '0';
			}
			
			int temp = num[t[0]];
			
			for(int i = 0; i < cnt; i++) {
				shift(t[i], num[t[i+1]], 1);	
				num[t[i]] = num[t[i+1]];
			}
			shift( t[cnt], temp, 1);
			num[t[cnt]] = temp;
		}
	}
	return 0;
}


4.

POJ - 2886 Who Gets the Most Candies


#include<cstdio>
#include<cstring>
const int maxn = 500010 << 2;
int S[maxn],L[maxn],R[maxn], ans[maxn >> 2], num[maxn >> 2];
char name[maxn >> 2][20];
int N, K, id;
void build(int u, int l, int r) {
	L[u] = l;
	R[u] = r;
	if(l == r) {
		S[u] = 1;
		return ;	
	} 
	int mid = (l + r) / 2;
	build(2 * u, l , mid);
	build(2 * u + 1, mid + 1, r);
	S[u] = S[2 * u + 1] + S[2 * u];
}

void Solve() {
	memset(ans,0,sizeof(ans));
	id = 0;
	for(int i = 1; i <= N; i++) {
		ans[i]++;
		for(int j = 2 * i; j <= N; j += i)	
			ans[j]++;
	}
	int MAX = ans[1];
	for(int i = 2; i <= N; i++) {
		if(ans[i] > MAX) {
			MAX = ans[i];
			id = i;	
		} 	
	}
}

int modify(int key, int u) {
	S[u]--;
	if(L[u] == R[u]) 
		return L[u];
	if(S[2 * u] >= key)
		return modify(key, 2 * u);
	else
		return modify(key - S[2 * u], 2 * u + 1);
}

int main() {
	while(scanf("%d%d",&N, &K) != EOF) {
		Solve();
		for(int i = 1; i <= N; i++)
			scanf("%s %d",name[i],&num[i]);
		build(1,1,N);	
		num[0] = 0;
		N = id;
		int pos = 0;
		int sum = S[1];
		while(N--) {
			if(num[pos] > 0)
				K = ( ( K - 1 + num[pos] - 1) % sum + sum )  % sum + 1;
			else
				K = ( (K - 1 + num[pos] ) % sum + sum) % sum + 1;
			pos = modify(K,1);
			sum = S[1];
		}
		printf("%s %d\n",name[pos],ans[id]);
	}

	return 0;
}