http://blog.sina.com.cn/s/blog_6bddecdc0102uyp3.html
hdu-4889-Scary Path Finding Algorithm
problem
think
构造。按照题解的构造方法写了一个。想不出来啊。
code
int bit[100];
long long spfa_slf(int C, int nn) {
int n,m;
n = nn*2+1;
m = n*3;
vector<pair<int,int> > edges[111];
for(int i = 1; i <= nn; ++i){
//cout<<i<<" "<<C<<" "<<nn<<endl;
int id1 = 2*i - 1;
int id2 = 2*i;
int id3 = 2*i+1;
int x, y, w;
x = id1;
y = id2;
w = 0;
//cout<<x<<" "<<y<<" "<<w<<endl;
edges[x].push_back(make_pair(y,-w));
x = id1;
y = id3;
w = bit[nn-i];
//cout<<x<<" "<<y<<" "<<w<<endl;
edges[x].push_back(make_pair(y,-w));
x = id2;
y = id3;
w = bit[nn-i+1];
//cout<<x<<" "<<y<<" "<<w<<endl;
edges[x].push_back(make_pair(y,-w));
}
deque<int> q;
vector<long long> dist(n+1, ~0ULL>>1);
vector<bool> inQueue(n+1, false);
dist[1] = 0;
q.push_back(1);
inQueue[1] = true;
int doge = 0;
while(!q.empty()) {
int x = q.front(); q.pop_front();
//cout<<x<<endl;
//cout<<"+++++++ "<<q.size()<<" "<<doge<<" "<<C<<endl;
if(doge++ > C) {
puts("doge");
//cout<<endl<<" "<<C<<endl;
return 233;
}
for(vector<pair<int,int> >::iterator it = edges[x].begin();
it != edges[x].end();++it) {
int y = it->first;
int w = it->second;
if(dist[y] > dist[x] + w) {
dist[y] = dist[x] + w;
if(!inQueue[y]) {
inQueue[y] = true;
if(!q.empty() && dist[y] > dist[q.front()])
q.push_back(y);
else
q.push_front(y);
}
}
}
inQueue[x] = false;
}
return dist[n];
}
int main(){
int C;
bit[0] = 1;
for(int i = 1; i <= 31; ++i) bit[i] = bit[i-1] * 2;
bit[0] = 0;
while(scanf("%d", &C) != EOF){
if(C < 0){
puts("2 1");
puts("1 2 1");
continue;
}
++C;
int n = 1;
int N = 2;
while(N < C){
++n;
N *= 2;
}
printf("%d %d\n", 2*n+1, 3*n);
for(int i = 1; i <= n; ++i){
int id1 = 2*i - 1;
int id2 = 2*i;
int id3 = 2*i+1;
printf("%d %d %d\n", id1, id2, 0);
printf("%d %d %d\n", id1, id3, -bit[n-i]);
printf("%d %d %d\n", id2, id3, -bit[n-i+1]);
}
//spfa_slf(C, n);
}
return 0;
}
hdu-4893-Wow! Such Sequence!
problem
n个点,m个操作。
1 x y,第x个数加y
2 x y,第x个数到第y个数的和
3 x y,第x个数到第y个数分别变成和他差的绝对值最小的那个fib数,如果前后两个一样变成前一个。
think
线段树。存两个值,一个是实际值,一个是fib值。
code
const int N = 111111;
ll fb[10000];
ll t[N<<2][2];
int L[N<<2], R[N<<2];
int op[N<<2];//0 1 2
int n, m;
void gao() {
fb[0] = 1, fb[1] = 1;
for (int i = 2; i <= 91; i++) fb[i] = fb[i - 1] + fb[i - 2];//, cout<<fb[i]<<endl;
}
void build(int l, int r, int k){
L[k] = l;
R[k] = r;
op[k] = 0;
t[k][0] = 0;
t[k][1] = r - l + 1;
if(l == r) return;
int mid = ( l + r) >> 1;
build(l, mid, k<<1);
build(mid+1, r, k<<1|1);
}
void down(int k){
if(op[k] == 1){
op[k<<1] = 1;
t[k<<1][0] = t[k<<1][1];
op[k<<1|1] = 1;
t[k<<1|1][0] = t[k<<1|1][1];
}
op[k] = 0;
}
void up(int k){
op[k] = 0;
for(int i = 0; i <= 1; ++i) t[k][i] = t[k<<1][i] + t[k<<1|1][i];
}
void update1(int a, int k, ll d){
if(a== L[k] && a == R[k]){
ll tmp = t[k][0] + d;
t[k][0] = tmp;
int fuck = lower_bound(fb, fb + 92, tmp) - fb;
if (fb[fuck] == tmp) t[k][1] = fb[fuck];
else if (fuck == 0) t[k][1] = 1;
else {
if (tmp - fb[fuck - 1] > fb[fuck] - tmp) t[k][1] = fb[fuck];
else t[k][1] = fb[fuck - 1];
}
op[k] = 0;
return ;
}
down(k);
int mid = (L[k] + R[k]) >> 1;
if(a<=mid) update1(a, k<<1, d);
else update1(a, k<<1|1, d);
up(k);
}
void update2(int l, int r, int k){
if(l == L[k] && r == R[k]){
op[k] = 1;
t[k][0] = t[k][1];
return ;
}
down(k);
int mid = (L[k] + R[k]) >> 1;
if(r <= mid) update2(l, r, k<<1);
else if(l > mid) update2(l, r, k<<1|1);
else{
update2(l, mid, k<<1);
update2(mid+1, r, k<<1|1);
}
up(k);
}
ll query(int l, int r, int k){
if(l == L[k] && r == R[k]) return t[k][0];
down(k);
int mid = (L[k] + R[k]) >> 1;
if(r <= mid) return query(l, r, k<<1);
else if(l > mid) return query(l, r, k<<1|1);
else return (query(l, mid, k<<1) + query(mid+1, r, k<<1|1));
}
int main () {
gao();
while(scanf("%d%d", &n, &m) != EOF){
build(1, n, 1);
for(int i = 0; i < m; ++i){
int oo, l, r;
ll d;
scanf("%d%d", &oo, &l);
if(oo == 1){
scanf("%I64d", &d);
update1(l, 1, d);
} else if(oo == 2){
scanf("%d", &r);
printf("%I64d\n", query(l, r, 1));
} else {
scanf("%d", &r);
update2(l, r, 1);
}
}
}
return 0;
}