签到题 J Different Integers(树状数组)
题目大意:给一个长为n的数组,每一个询问给两个数字i, j ,询问1~i, j~n这两个区间中有多少不同的数字,真的像是莫队裸题,但是两个区间是分隔的,所以可以考虑将数组延长一倍,即num[i] = num[i+n],这样就可以变成一段区间中查询了,不过这样会T.....参考了题解的做法还是比较好用的,写法非常巧妙。记录数字i第一次和最后一次出现的位置分别为first[i], last[i],按每个询问的rhs从小到大排序后,遍历num数组。遍历序号为i,每次遍历处理询问和维护一个树状数组,①只有当某个询问的 rhs == i 时处理该询问②维护树状数组,首先我们可以想到假如某个数x,当last[x] == i 时,下个遍历时下个询问的rhs必然会大于这个last[x](因为是从1~n遍历),所以当这次遍历过后,剩下的询问rhs全部大于last[x],所有右边区间rhs~n已经没有x了,这个时候只要看前面lhs是不是小于first[x]就知道这个数在不在询问区间了,这个时候就可以维护一个前缀和,sum[i]表示表示有多少个数的first值是在1~i内的。
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <vector> 5 #include <map> 6 #include <string> 7 #include <algorithm> 8 #include <time.h> 9 10 #define SIGMA_SIZE 26 11 #define lson rt<<1 12 #define rson rt<<1|1 13 #define lowbit(x) (x&-x) 14 #pragma warning ( disable : 4996 ) 15 16 using namespace std; 17 typedef long long LL; 18 inline LL LMax(LL a,LL b) { return a>b?a:b; } 19 inline LL LMin(LL a,LL b) { return a>b?b:a; } 20 inline int Max(int a,int b) { return a>b?a:b; } 21 inline int Min(int a,int b) { return a>b?b:a; } 22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); } 23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm 24 const LL INF = 0x3f3f3f3f3f3f3f3f; 25 const LL mod = 1000000007; 26 const double eps = 1e-8; 27 const int inf = 0x3f3f3f3f; 28 const int maxk = 1e4+5; 29 const int maxn = 1e5+10; 30 31 int n, q, tot; 32 int first[maxn], last[maxn]; 33 int num[maxn], ans[maxn], _count[maxn]; 34 35 struct node { 36 int lhs, rhs, id; 37 }p[maxn]; 38 39 void add( int x, int d ) 40 { 41 while ( x > 0 ) 42 { 43 _count[x] += d; 44 x -= lowbit(x); 45 } 46 } 47 48 int sum(int x) 49 { 50 int s = 0; 51 while ( x <= n ) 52 { 53 s += _count[x]; 54 x += lowbit(x); 55 } 56 return s; 57 } 58 59 bool cmp(const node& a, const node &b) 60 { return a.rhs < b.rhs; } 61 62 void init() 63 { 64 tot = 0; 65 memset(first, -1, sizeof(first)); 66 memset(last, -1, sizeof(last)); 67 memset(_count, 0, sizeof(_count)); 68 69 for (int i = 1; i <= n; i++) 70 { 71 scanf("%d", &num[i]); 72 if (first[num[i]] == -1) 73 { tot++; first[num[i]] = i;} 74 last[num[i]] = i; 75 } 76 77 for (int i = 1; i <= q; i++) 78 { 79 scanf("%d %d", &p[i].lhs, &p[i].rhs); 80 p[i].id = i; 81 } 82 sort(p+1, p+1+q, cmp); 83 } 84 85 86 int main() 87 { 88 while (~scanf("%d %d", &n, &q)) 89 { 90 init(); 91 92 for (int i = 1, k = 1; i <= n; i++) 93 { //如果有边界到达了某一点i,则可以开始处理左边界 94 while (k <= q && p[k].rhs == i) 95 { 96 ans[p[k].id] = tot - sum(p[k].lhs); 97 k++; 98 } 99 100 if (last[num[i]] == i) 101 add(first[num[i]]-1, 1); 102 } 103 104 for ( int i = 1; i <= q; i++ ) 105 printf("%d ", ans[i]); 106 } 107 108 return 0; 109 }
签到题? D Two Graphs
题目大意:给两个简单图G1(V, E1), G2(V,E2) ,问有多少个G2的子图与G1是同构的,想了好多骚操作,,结果hash去重就可以了
1 #include <iostream> 2 #include <string.h> 3 #include <cstdio> 4 #include <vector> 5 #include <set> 6 #include <string> 7 #include <algorithm> 8 #include <time.h> 9 10 #define SIGMA_SIZE 26 11 #define lson rt<<1 12 #define rson rt<<1|1 13 #define lowbit(x) (x&-x) 14 #pragma warning ( disable : 4996 ) 15 16 using namespace std; 17 typedef long long LL; 18 inline LL LMax(LL a,LL b) { return a>b?a:b; } 19 inline LL LMin(LL a,LL b) { return a>b?b:a; } 20 inline int Max(int a,int b) { return a>b?a:b; } 21 inline int Min(int a,int b) { return a>b?b:a; } 22 inline int gcd( int a, int b ) { return b==0?a:gcd(b,a%b); } 23 inline int lcm( int a, int b ) { return a/gcd(a,b)*b; } //a*b = gcd*lcm 24 const LL INF = 0x3f3f3f3f3f3f3f3f; 25 const LL mod = 1000000007; 26 const double eps = 1e-8; 27 const int inf = 0x3f3f3f3f; 28 const int maxk = 1e4+5; 29 const int maxn = 1e5+10; 30 31 struct edge2 { 32 int x, y; 33 }edge[100]; 34 int v, e1, e2; 35 int g1[10][10], g2[10][10], num[10]; 36 37 void init() 38 { 39 memset(g1, 0, sizeof(g1)); 40 memset(g2, 0, sizeof(g2)); 41 for ( int i = 1; i <= v; i++ ) 42 num[i] = i; 43 44 int x, y; 45 for ( int i = 1; i <= e1; i++ ) 46 { scanf("%d %d", &x, &y); g1[x][y] = 1; g1[y][x] = 1; } 47 for ( int i = 1; i <= e2; i++ ) 48 { 49 scanf("%d %d", &x, &y); g2[x][y] = 1; g2[y][x] = 1; 50 edge[i].x = x; 51 edge[i].y = y; 52 } 53 54 } 55 56 int main() 57 { 58 while (~scanf("%d %d %d", &v, &e1, &e2)) 59 { 60 init(); 61 62 63 set<long long> ss; 64 do { 65 int cnt = 0; 66 long long has = 0; 67 for (int i = 1; i <= e2; i++) 68 { 69 if (g1[num[edge[i].x]][num[edge[i].y]]) 70 { 71 has = has*177 + i; 72 has %= mod; 73 cnt++; 74 } 75 } 76 77 if (cnt == e1) 78 ss.insert(has); 79 80 }while(next_permutation(num+1, num+1+v)); 81 82 printf("%zd ", ss.size()); 83 } 84 85 return 0; 86 }