标签:des os io ar strong for art 代码 sp
C. Appleman and a Sheet of Paper
time limit per test
2 seconds
memory limit per test
256 megabytes
Appleman has a very big sheet of paper. This sheet has a form of rectangle with dimensions 1 × n. Your task is help Appleman with folding of such a sheet. Actually, you need to perform q queries. Each query will have one of the following types:
Please look at the explanation of the first test example for better understanding of the problem.
Input
The first line contains two integers: n and q (1 ≤ n ≤ 105; 1 ≤ q ≤ 105) — the width of the paper and the number of queries.
Each of the following q lines contains one of the described queries in the following format:
Output
For each query of the second type, output the answer.
Sample test(s)
input
7 4
1 3
1 2
2 0 1
2 1 2
output
4
3
input
10 9
2 2 9
1 1
2 0 1
1 8
2 0 8
1 2
2 1 3
1 4
2 2 4
output
7
2
10
4
5
题意:给你一张1*n的纸片,有2种操作:(1)1 x,在x的地方将左半部分向左边折叠。(2)2 x y 求[x,y]区间的纸片厚度总和
思路:其实是一道模拟题,因为N的范围,和多次求区间和,明显应该用树状数组。。在折叠的过程中折叠后的纸片会变小。在1—N的线段上覆盖的长度也在减小,每次折叠完会多出一些没用的区间(想象一下不用将纸片前移到0,只是不断的折叠),所以当折叠过去后超过当前的右边界。。可以等效为将右边的向左折,相当于翻转了一次。。(不能向左折因为超出的部分会加上没用的区间的厚度)下次再进行折叠操作的时候就看成起始端在右边。。你可以设置标记。。2次翻转就恢复正常样子
代码:(参考别人的):
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 100005;
int bit[maxn];
int n, q;
int lowbit(int x)
{
return x & -x;
}
void add(int x, int y)
{
while(x <= n)
{
bit[x] += y;
x += lowbit(x);
}
}
int getsum(int x)
{
int ans = 0;
while(x > 0)
{
ans += bit[x];
x -= lowbit(x);
}
return ans;
}
int main()
{
int t, p, x, y;
scanf("%d%d", &n, &q);
memset(bit, 0, sizeof(bit));
for(int i = 1; i <= n; i++) add(i, 1);
bool flag = 0;
int l = 1, r = n;
for(int i = 0; i < q; i++)
{
scanf("%d", &t);
if(t == 1)
{
scanf("%d", &p);
if(!flag) p = l + p;//根据纸片是否与正常翻转过来重新计算折纸点
else p = r - p + 1;
if(2 * p > r + l + 1)//右半部分小,向左边叠
{
for(int j = p; j <= r; j++)
{
int u = getsum(j) - getsum(j - 1);//下标从0开始对树状数组处理时都要减1.下同
add(2 * p - j- 1, u);
}
r = p - 1;
if(flag == 0) flag ^= 1;
}
else
{
for(int j = l; j < p; j++)
{
int u = getsum(j) - getsum(j - 1);
add(2 * p - 1 - j, u);
}
l = p;
if(flag == 1) flag ^= 1;
}
}
else
{
scanf("%d%d", &x, &y);
if(!flag)
{
x = l + x - 1;
y = l + y - 1;
}
else
{
int t = x;
x = r - y;
y = r - t;
}
printf("%d\n", getsum(y) - getsum(x));
}
}
return 0;
}
下面一种类似,还省去了标记:只用看L与R 的关系判断上次有没有翻转过
#include <cstdio>
#include <stdlib.h>
#include <algorithm>
using namespace std;
#define REP(i,n) for((i)=0;(i)<(int)(n);(i)++)
int tree[1<<20];
void add(int pos, int val)
{
for (int i = pos; i<(1<<20); i = ((i) | (i + 1))) tree[i] += val;
}
int sum(int pos)
{
int ans = 0;
for (int i = pos; i>0; i = ((i)&(i - 1))) ans += tree[i - 1];
return ans;
}
int get(int x)
{
return sum(x + 1) - sum(x);
}
void update(int x, int val)
{
add(x, val);
}
int sum(int L, int R)
{
return sum(R) - sum(L);
}
int main()
{
int N, Q, i, j;
scanf("%d%d", &N, &Q);
int L = 0, R = N;
REP(i, N) update(i, 1);
REP(j, Q)
{
int type;
scanf("%d", &type);
if (type == 1)
{
int p;
scanf("%d", &p);
int M;
if (L < R) M = L + p;
else M = L - p;
if (L > R) swap(L, R);
int w = min(M - L, R - M);
int L2, R2;
if (M - L <= R - M)
{
REP(i, w)
{
int tmp = get(M - 1 - i);
update(M + i, tmp);
}
L2 = M;
R2 = R;
}
else
{
REP(i, w)
{
int tmp = get(M + i);
update(M - 1 - i, tmp);
}
L2 = M;
R2 = L;
}
L = L2;
R = R2;
}
else
{
int l, r;
scanf("%d%d", &l, &r);
int ans = 0;
if (L < R) ans = sum(L + l, L + r);
else ans = sum(L - r, L - l);
printf("%d\n", ans);
}
}
}
461C. Appleman and a Sheet of Paper(树状数组)
标签:des os io ar strong for art 代码 sp
原文地址:http://www.cnblogs.com/ACMDoli/p/3957931.html