acmicpc 解题报告汇总:http://acmicpc.info/archives/823
1:
线段树
(i-a)%k = 0 即i%k=a%k
节点维护一个二维数组add, add[a][b]=c,表示该区间下标i%a=b的加c
那么, update(l, r, k, l%k, v)这样就可以分到子区间了
但是, 这样会爆内存,因为a%b<b,可以节省一半, 这样就过了..
#pragma warning (disable: 4786)
#include "stdio.h"
#include "string.h"
#include "iostream"
#include "algorithm"
#include "vector"
#include "map"
#include "set"
using namespace std;
const int N = 50005;
int seg[N*3][55], da[N];
void update(int l, int r, int a, int b, int c, int rt, int L, int R) {
if(l <= L && R <= r) {
int i, ii = b;
for(i = 1; i < a; ++i) {
ii += i;
}
seg[rt][ii] += c;
return;
}
int mid = (L+R)>>1;
if(l <= mid) {
update(l, r, a, b, c, rt<<1, L, mid);
}
if(r > mid) {
update(l, r, a, b, c, rt<<1|1, mid+1, R);
}
}
int query(int x, int rt, int L, int R) {
int mid = (L+R)>>1, res = 0, i, j, ii;
for(i = 1; i <= 10; ++i)
{
ii = x%i;
for(j = 1; j < i; ++j) {
ii += j;
}
res += seg[rt][ii];
}
if(x <= L && R <= x) {
return res;
}
if(x <= mid) {
res += query(x, rt<<1, L, mid);
}
if(x > mid) {
res += query(x, rt<<1|1, mid+1, R);
}
return res;
}
int main()
{
int n, q, i;
while(~scanf("%d", &n))
{
for(i = 1; i <= n; ++i) {
scanf("%d", &da[i]);
}
memset(seg, 0, sizeof(seg));
scanf("%d", &q);
int t, l, r, k, v;
while(q--) {
scanf("%d", &t);
if(t==1) {
scanf("%d%d%d%d", &l, &r, &k, &v);
update(l, r, k, l%k, v, 1, 1, n);
}
else if(t==2) {
scanf("%d", &i);
printf("%d\n", da[i]+query(i, 1, 1, n));
}
}
}
return 0;
}
2:
先按第一维排序,然后第二维
然后对a的每个i,找出小于a[i].h的b.h,将对应的w塞到集合里
刚才已经保证了第一维满足了
然后贪心的从集合里面找a[i]能覆盖的最大的w
#pragma warning (disable: 4786)
#include "stdio.h"
#include "string.h"
#include "iostream"
#include "algorithm"
#include "vector"
#include "map"
#include "set"
using namespace std;
typedef pair<int,int> PII;
vector<PII> a, b;
multiset<int> c;
multiset<int>::iterator it;
int main()
{
int t, n, h, w, i, j;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
a.clear();
b.clear();
for(i = 0; i < n; ++i) {
scanf("%d%d", &h, &w);
a.push_back(make_pair(h, w));
}
for(i = 0; i < n; ++i) {
scanf("%d%d", &h, &w);
b.push_back(make_pair(h, w));
}
sort(a.begin(), a.end());
sort(b.begin(), b.end());
int ans = 0;
c.clear();
for(i=j=0; i<a.size(); ++i) {
while(j<b.size() && b[j].first<=a[i].first) {
c.insert(b[j].second);
++j;
}
it = c.upper_bound(a[i].second);
if(it != c.begin() && !c.empty()) {
--it;
c.erase(it);
++ans;
}
}
printf("%d\n", ans);
}
return 0;
}
8:
dfs求出每个点的取值范围, 如果出现up<down的, 则矛盾...
#pragma warning (disable: 4786)
#include "cstdio"
#include "cstring"
#include "cassert"
#include "iostream"
#include "algorithm"
#include "vector"
#include "map"
#include "set"
using namespace std;
typedef __int64 ll;
typedef pair<ll, ll> PII;
typedef vector<int> VI;
#define max(a, b) a>b?a:b
#define min(a, b) a<b?a:b
const int N = 11111;
const ll inf = 0x7fffffffffffffff;
VI mat[N];
PII seg[N];
int ok;
void calc(int i, ll d, ll u) {
ll nd = max(d, seg[i].first),
nu = min(u, seg[i].second);
if(nu < nd) {
ok = 0;
}
seg[i].first = nd;
seg[i].second = nu;
}
void dfs(int rt) {
if(!ok || mat[rt].size() == 0) { return; }
int i;
ll dw = 1, up = inf;
for(i = 0; i < mat[rt].size(); ++i) {
dfs(mat[rt][i]);
dw += seg[mat[rt][i]].first;
}
calc(rt, dw, up);
}
int main()
{
char c;
int n, m, f, a, b, i;
ll dw, up;
while(~scanf("%d", &n)) {
for(i = 1; i <= n; ++i) {
seg[i].first = 1;
seg[i].second = inf;
mat[i].clear();
}
for(i = 2; i <= n; ++i) {
scanf("%d", &f);
mat[f].push_back(i);
}
ok = 1;
scanf("%d", &m);
while(m--) {
scanf("%d %c %d", &a, &c, &b);
dw = 1;
up = inf;
if(c=='=') { dw = up = b; }
else if(c=='<') { up = b-1; }
else if(c=='>') { dw = b+1; }
else { assert(0>1); }
calc(a, dw, up);
}
dfs(1);
puts(ok?"True":"Lie");
}
return 0;
}
11:
暴力, 3^15,
敲代码的时候两个set轮换...
卡过去了...
#pragma warning (disable: 4786)
#include "stdio.h"
#include "string.h"
#include "iostream"
#include "algorithm"
#include "vector"
#include "map"
#include "set"
using namespace std;
struct node{
int a, b, c;
node() { a=b=c=0; }
node(int aa, int bb, int cc):a(aa), b(bb), c(cc){}
bool operator < (const node & tmp) const
{
if(a!=tmp.a) { return a<tmp.a; }
else if(b!=tmp.b) { return b<tmp.b; }
else { return c<tmp.c; }
}
bool operator == (const node & tmp) const
{
return (a==tmp.a && b==tmp.b && c==tmp.c);
}
node operator + (const node & tmp) const
{
int aa=a+tmp.a, bb=b+tmp.b, cc=c+tmp.c;
if(aa>bb) { swap(aa, bb); }
if(aa>cc) { swap(aa, cc); }
if(bb>cc) { swap(bb, cc); }
return node(aa, bb, cc);
}
};
int isok(const node& n) {
return (n.a+n.b>n.c);
}
vector<int> v;
set<node> s[2];
int main()
{
int t, n, x, i;
scanf("%d", &t);
while(t--) {
scanf("%d", &n);
v.clear();
for(i=0; i<n; ++i) {
scanf("%d", &x);
v.push_back(x);
}
s[0].clear();
s[0].insert(node());
int a=0, b=1;
set<node>::iterator it;
for(i=0; i<n; ++i)
{
s[b].clear();
for(it=s[a].begin(); it!=s[a].end(); ++it) {
s[b].insert(*it+node(v[i], 0, 0));
s[b].insert(*it+node(0, v[i], 0));
s[b].insert(*it+node(0, 0, v[i]));
}
swap(a, b);
}
int ans = 0;
for(it=s[a].begin(); it!=s[a].end(); ++it) {
if(isok(*it)) { ++ans; }
}
printf("%d\n", ans);
}
return 0;
}