您的位置:首页 > 理论基础 > 计算机网络

2012长春网络赛

2012-09-08 18:27 387 查看
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
;

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
;
PII seg
;

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: