福州大学第十一届程序设计
现在写几个自己比赛RE到死的题目,吸取教训;
Problem 2169 shadow
Accept: 109 Submit: 322
Time Limit: 1000 mSec Memory Limit : 32768 KB
Problem Description
YL是shadow国的国王,shadow国有N个城市。为了节省开支,shadow国只有N-1条道路,这N-1条道路使得N个城市连通。某一年,shadow国发生了叛乱,叛军占领了多个城市,王都岌岌可危。王都为编号为1的城市,除了王都外有K个城市有YL的军队。现在这K支军队要向王都进军,并且消灭沿途经过的城市中的叛军。现给出N个城市的道路情况以及城市的叛军数量,问总共需要消灭多少叛军?
Input
第一行输入两个整数N,K,接下来输入N(1<=N<=100000)个整数Ai(0<=Ai<=10000),表示第i个城市的叛军数量。接下来输入K个大于等于1且小于等于N的整数,表示有军队的城市的编号。数据保证王都以及有军队的城市没有叛军。接下来输入N-1行,每行两个整数u、v,表示连接u和v的一条道路。每支军队只能沿着道路走,并且是其所在城市与王都之间的最短路线走。
Output
输出一行一个整数表示消灭的叛军数量。
Sample Input
4 2 0 3 0 0 3 4 1 2 2 3 2 4
Sample Output
3
比赛的是贡献了20多次RE+TLE,真无语,居然卡VECTOR,看RP,有些人的VECTORpassed,
数组邻接表模式:#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=200010;
struct node{
int v,next;
}edg[maxn];
int head[2*maxn];
int tt;
int n,m,k;
int a[maxn];
int b[maxn],num[maxn];
int pre[maxn];
long long ans;
void add(int u,int v)
{
edg[tt].v=v;
edg[tt].next=head[u];
head[u]=tt++;
}
void dfs(int x)
{
for (int i=head[x];i!=-1;i=edg[i].next){
int y=edg[i].v;
if (!b[y])
{
b[y]=1;
pre[y]=x;
dfs(y);
}
}
}
int main()
{
while (scanf("%d%d",&n,&k)!=EOF)
{
memset(head,-1,sizeof(head));
memset(pre,-1,sizeof(pre));
memset(b,0,sizeof(b));
tt=0;
ans=0;
for (int i=1;i<=n;i++) scanf("%d",&num[i]);
for (int i=1;i<=k;i++)
scanf("%d",&a[i]);
for (int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1);
memset(b,0,sizeof(b));
for (int i=1;i<=k;i++)
{
int x=a[i];
while (x!=-1&&!b[x])
{
ans+=num[x];
b[x]=1;
x=pre[x];
}
}
printf("%d\n",ans);
}
return 0;
#include<string.h>
#include<string>
#include<algorithm>
#include<vector>
using namespace std;
const int maxn=200010;
struct node{
int v,next;
}edg[maxn];
int head[2*maxn];
int tt;
int n,m,k;
int a[maxn];
int b[maxn],num[maxn];
int pre[maxn];
long long ans;
void add(int u,int v)
{
edg[tt].v=v;
edg[tt].next=head[u];
head[u]=tt++;
}
void dfs(int x)
{
for (int i=head[x];i!=-1;i=edg[i].next){
int y=edg[i].v;
if (!b[y])
{
b[y]=1;
pre[y]=x;
dfs(y);
}
}
}
int main()
{
while (scanf("%d%d",&n,&k)!=EOF)
{
memset(head,-1,sizeof(head));
memset(pre,-1,sizeof(pre));
memset(b,0,sizeof(b));
tt=0;
ans=0;
for (int i=1;i<=n;i++) scanf("%d",&num[i]);
for (int i=1;i<=k;i++)
scanf("%d",&a[i]);
for (int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs(1);
memset(b,0,sizeof(b));
for (int i=1;i<=k;i++)
{
int x=a[i];
while (x!=-1&&!b[x])
{
ans+=num[x];
b[x]=1;
x=pre[x];
}
}
printf("%d\n",ans);
}
return 0;
} 换做VECTOR就不可以,。。。。
对了,还有F题 Problem 2171 防守阵地 II的树状数组写法,完爆那些线段树
树状数组真是好东西
线段树写法:#include <cstdio>
#include <algorithm>
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define LL long long
const int maxn = 111111;
LL add[maxn<<2];
LL sum[maxn<<2];
void PushUp(int rt) {
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int m) {
if (add[rt]) {
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += add[rt] * (m - (m >> 1));
sum[rt<<1|1] += add[rt] * (m >> 1);
add[rt] = 0;
}
}
void build(int l,int r,int rt) {
add[rt] = 0;
if (l == r) {
scanf("%lld",&sum[rt]);
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt) {
if (L <= l && r <= R) {
add[rt] += c;
sum[rt] += (LL)c * (r - l + 1);
return ;
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
if (L <= m) update(L , R , c , lson);
if (m < R) update(L , R , c , rson);
PushUp(rt);
}
LL query(int L,int R,int l,int r,int rt) {
if (L <= l && r <= R) {
return sum[rt];
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
LL ret = 0;
if (L <= m) ret += query(L , R , lson);
if (m < R) ret += query(L , R , rson);
return ret;
}
int main() {
int n,m,q;
while (scanf("%d%d%d",&n,&m,&q)!=EOF){
build(1,n,1);
for (int i=1;i<=q;i++)
{
int a;
scanf("%d",&a);
printf("%lld\n",query(a,a+m-1,1,n,1));
update(a,a+m-1,-1,1,n,1);
}
}
return 0;
using namespace std;
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
#define LL long long
const int maxn = 111111;
LL add[maxn<<2];
LL sum[maxn<<2];
void PushUp(int rt) {
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int m) {
if (add[rt]) {
add[rt<<1] += add[rt];
add[rt<<1|1] += add[rt];
sum[rt<<1] += add[rt] * (m - (m >> 1));
sum[rt<<1|1] += add[rt] * (m >> 1);
add[rt] = 0;
}
}
void build(int l,int r,int rt) {
add[rt] = 0;
if (l == r) {
scanf("%lld",&sum[rt]);
return ;
}
int m = (l + r) >> 1;
build(lson);
build(rson);
PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt) {
if (L <= l && r <= R) {
add[rt] += c;
sum[rt] += (LL)c * (r - l + 1);
return ;
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
if (L <= m) update(L , R , c , lson);
if (m < R) update(L , R , c , rson);
PushUp(rt);
}
LL query(int L,int R,int l,int r,int rt) {
if (L <= l && r <= R) {
return sum[rt];
}
PushDown(rt , r - l + 1);
int m = (l + r) >> 1;
LL ret = 0;
if (L <= m) ret += query(L , R , lson);
if (m < R) ret += query(L , R , rson);
return ret;
}
int main() {
int n,m,q;
while (scanf("%d%d%d",&n,&m,&q)!=EOF){
build(1,n,1);
for (int i=1;i<=q;i++)
{
int a;
scanf("%d",&a);
printf("%lld\n",query(a,a+m-1,1,n,1));
update(a,a+m-1,-1,1,n,1);
}
}
return 0;
}
随性Code