题目:http://codeforces.com/contest/380
A
题意:实现两种操作
1 在数组的最后插入一个数; 2将数组的钱L部分复制c次, 问任意位置的元素值
思路:递归求解, 每次执行操作后记录下当前数组的总长度和此操作的类型,求解时二分查找该位置为第P次操作,若该操作为1, 则直接输出答案,否则计算该位置为复制前L长的位置v,递归求解
#include
int a[100010], b[100010], ans[100010];
__int64 f[100010];
int k, n, m;
int binsearch(__int64 x)
{
int l = 1, r = n;
int ans = 0;
while(l <= r)
{
int m = (l+r) / 2;
if(f[m] < x)
{
ans = m;
l = m+1;
}
else
r = m-1;
}
return ans;
}
int solve(__int64 x)
{
int p = binsearch(x);
if(b[p+1] == -1)
return a[p+1];
__int64 v = (x-f[p]) % a[p+1];
if(v == 0)
v = a[p+1];
return solve(v);
}
int main()
{
scanf("%d", &n);
for(int i=1; i<=n; i++)
{
scanf("%d", &k);
if(k == 1)
{
scanf("%d", &a[i]);
b[i] = -1;
f[i] = f[i-1] + 1;
}
else
{
scanf("%d %d", &a[i], &b[i]);
f[i] = f[i-1] + a[i]*b[i];
}
}
__int64 x;
scanf("%d", &m);
for(int i=1; i<=m; i++)
{
scanf("%I64d", &x);
ans[i] = solve(x);
}
printf("%d", ans[1]);
for(int i=2; i<=m; i++)
printf(" %d", ans[i]);
puts("");
return 0;
}
C
题意:输入一个字符串, 然后实现m次操作, 每次操作输入了l, r, 要求输出该区间内最大的正确括号长度
思路:采用线段树, 节点维护三个域,正确括号数,未匹配左括号数, 未匹配右括号数
#include
#include
#include
using namespace std;
typedef struct
{
int s, l, r;
}node;
node a[1000010*4];
char s[1000010];
int ql, qr, n, m;
void construct(int o, int l, int r)
{
if(l == r)
{
a[o].s = 0;
if(s[l] == '(')
a[o].l = 1;
else
a[o].r = 1;
return;
}
int m = (l+r) / 2;
construct(2*o, l, m);
construct(2*o+1, m+1, r);
a[o].s = a[2*o].s + a[2*o+1].s + min(a[2*o].l, a[2*o+1].r);
a[o].l = a[2*o].l + a[2*o+1].l - min(a[2*o].l, a[2*o+1].r);
a[o].r = a[2*o].r + a[2*o+1].r - min(a[2*o].l, a[2*o+1].r);
}
void query(int o, int l, int r, int &v1, int &v2, int &v3)
{
if(ql<=l && qr>=r)
{
v1 = a[o].l, v2 = a[o].r, v3 = a[o].s;
return;
}
if(ql>r || qr